Compare commits
170 Commits
Author | SHA1 | Date |
---|---|---|
Lephenixnoir | 8c5f68f16e | |
Lephenixnoir | fc9026798d | |
Lephenixnoir | 3775f28536 | |
Lephenixnoir | 5d51f205b9 | |
Lephenixnoir | 3e2f7f0aa0 | |
Lephenixnoir | 71ddfff567 | |
Lephenixnoir | 4bec7be97f | |
Lephenixnoir | fff06099a1 | |
Lephenixnoir | e7349aa227 | |
Lephenixnoir | dfb73611f9 | |
Lephenixnoir | b804cb7583 | |
Lephenixnoir | 38c0ec1d15 | |
Lephenixnoir | eaf5f43da4 | |
Lephenixnoir | c14f770483 | |
Lephenixnoir | 430fe06adc | |
Sylvain PILLOT | d298d0538d | |
Lephenixnoir | 3523a83bda | |
Lephenixnoir | ae3a135a81 | |
Lephenixnoir | 30fcf592d1 | |
Lephenixnoir | f9f94c999a | |
Lephenixnoir | 7abbcc1dfc | |
Lephenixnoir | a1848c0920 | |
Lephenixnoir | 3f02fd86ea | |
Lephenixnoir | 95eb40e25d | |
Lephenixnoir | 93e021f144 | |
Lephenixnoir | c84caa533d | |
Lephenixnoir | bcdb3b74ca | |
Sylvain PILLOT | 35b73ba954 | |
Sylvain PILLOT | 5f385d8bcc | |
Sylvain PILLOT | 05bfce99d6 | |
Sylvain PILLOT | 3e302b1b34 | |
Sylvain PILLOT | 26afb31ff2 | |
Lephenixnoir | a2b9c32cea | |
Sylvain PILLOT | 6225b1d667 | |
Sylvain PILLOT | 0f386bd779 | |
Sylvain PILLOT | 7fdf3aeb2e | |
Sylvain PILLOT | 263b9e83c8 | |
Sylvain PILLOT | 2cb2bc6e67 | |
Lephenixnoir | 0f867e9f72 | |
Sylvain PILLOT | d4dcc59d71 | |
Sylvain PILLOT | 9bc05bbf03 | |
Lephenixnoir | b1e39d3ab6 | |
Lephenixnoir | af8bacd271 | |
Lephenixnoir | d4501baadb | |
Lephenixnoir | 627c81c1b6 | |
Lephenixnoir | 262a90f15c | |
Sylvain PILLOT | 9156a21afa | |
Sylvain PILLOT | 226f82ec8c | |
Sylvain PILLOT | ba515dc168 | |
Lephenixnoir | 6ab101e1bd | |
Sylvain PILLOT | 6ae6d06387 | |
Sylvain PILLOT | e7ad1e267d | |
Lephenixnoir | 6969309cd7 | |
Lephenixnoir | eeb392a833 | |
Lephenixnoir | 00f009e0c2 | |
Sylvain PILLOT | 0fb961768a | |
Sylvain PILLOT | 8072e5b1a9 | |
Lephenixnoir | 7f647b57d7 | |
Lephenixnoir | b1ec8bcde4 | |
Sylvain PILLOT | e3fd785200 | |
Sylvain PILLOT | 12565ba8d2 | |
Sylvain PILLOT | 96077c1653 | |
Lephenixnoir | b9a457680b | |
Sylvain PILLOT | 226d94494f | |
Sylvain PILLOT | bca7048525 | |
Sylvain PILLOT | 0868d96d2b | |
Sylvain PILLOT | 2ac213cae0 | |
Sylvain PILLOT | c207c7b6f7 | |
Sylvain PILLOT | 774c8d0f44 | |
Lephenixnoir | 3a3ad0e155 | |
Lephenixnoir | 6af6f97df4 | |
Lephenixnoir | f3424c60a5 | |
Lephenixnoir | 9f860bd58a | |
Lephenixnoir | b6efd9ed31 | |
Lephenixnoir | e1bda048d0 | |
Lephenixnoir | 727b7fb032 | |
Lephenixnoir | 6547cf5fbc | |
Lephenixnoir | 2dddd209a0 | |
Lephenixnoir | f71cad03cf | |
Lephenixnoir | 5e2b33b148 | |
Lephenixnoir | c3dc438b82 | |
Damien George | dc2a4e3cbd | |
Damien George | 8438c8790c | |
Damien George | c3989e398f | |
robert-hh | 3d0b6276f3 | |
robert-hh | aea93a88f8 | |
robert-hh | 36d9e98fc6 | |
robert-hh | 8498b0b13e | |
iabdalkader | f34e27f178 | |
iabdalkader | 87d3f8b367 | |
Damien George | 2037edb5a2 | |
Lephenixnoir | 8823d1f473 | |
Lephenixnoir | cccc2787b5 | |
Lephenixnoir | 347e463e17 | |
Lephenixnoir | 61b2360b16 | |
Lephenixnoir | 5b52671c50 | |
Lephenixnoir | 70e15e9ed1 | |
Lephenixnoir | 01036c9611 | |
Lephenixnoir | e35ed0c2fb | |
mibi88 | 814b226158 | |
mibi88 | 7b7c00842f | |
mibi88 | 0b74e8cfb1 | |
mibi88 | 553af9b9c9 | |
mibi88 | 38f340cecd | |
Lephenixnoir | 3df7eae26c | |
Lephenixnoir | 7ecc558700 | |
Lephenixnoir | 8a498563b8 | |
Lephenixnoir | 4f63ac05d3 | |
Lephenixnoir | 63c4c8f609 | |
Lephenixnoir | e001880d5b | |
Lephenixnoir | da416f067f | |
mibi88 | 81d4bbdb1a | |
mibi88 | 16bd85a754 | |
Lephenixnoir | 53b2e6bfed | |
Lephenixnoir | b5d7c61c91 | |
Lephenixnoir | 0d20ae7929 | |
Lephenixnoir | ddab477c3e | |
Lephenixnoir | 189aadff1c | |
Lephenixnoir | 0da3395e89 | |
Lephenixnoir | dc062623da | |
Lephenixnoir | a4d5bc0752 | |
Lephenixnoir | dff23463b0 | |
Lephenixnoir | e85d84e802 | |
Lephenixnoir | 49e3f6a6af | |
Lephenixnoir | 9bdb18f49f | |
Lephenixnoir | 9684b6893f | |
Lephenixnoir | 46ca19aece | |
mibi88 | cb887885b9 | |
Lephenixnoir | d7d1df46bb | |
Lephenixnoir | 40a2de1a5f | |
Lephenixnoir | 8f5af62f9f | |
Lephenixnoir | edf57c6f07 | |
Lephenixnoir | e40f8cba15 | |
Lephenixnoir | 5051323860 | |
Lephenixnoir | 2cc8fe63e5 | |
Lephenixnoir | ed66b0d6a7 | |
mibi88 | b664e0ab9c | |
mibi88 | e3bda720ff | |
mibi88 | b39dc00203 | |
mibi88 | f9d6f55625 | |
mibi88 | c6e1666918 | |
mibi88 | 2ace52aff9 | |
mibi88 | a6fb6122db | |
mibi88 | 6fcce03e5c | |
Lephenixnoir | eeae10abc5 | |
Lephenixnoir | c1d2ca5048 | |
Lephenixnoir | 524562e8bc | |
Lephenixnoir | ab0f70effc | |
Lephenixnoir | 99f2156e5e | |
Lephenixnoir | bfa5de2cf9 | |
Lephenixnoir | 9ea4c17112 | |
Lephenixnoir | 5f1a066c94 | |
Lephenixnoir | 6c2aa39e56 | |
Lephenixnoir | 404d69aea4 | |
Lephenixnoir | 27822c2461 | |
Lephenixnoir | fa6aa00dae | |
Lephenixnoir | 4e529b5788 | |
Lephenixnoir | 2c238906e7 | |
Lephenixnoir | 8809f3eee4 | |
Lephenixnoir | d0654fc5e7 | |
Lephenixnoir | d6334be488 | |
Lephenixnoir | 3431000d2f | |
Lephenixnoir | ce4fefebbe | |
Lephenixnoir | e1df7e5f0b | |
Lephenixnoir | f930ff95db | |
Lephenixnoir | 1992ec0a49 | |
Lephenixnoir | c237e9874f | |
Lephenixnoir | a0d6c33275 | |
Lephenixnoir | f9b4c1f844 | |
Lephenixnoir | e33d85b1de |
|
@ -23,3 +23,6 @@ user.props
|
|||
|
||||
# MacOS desktop metadata files
|
||||
.DS_Store
|
||||
|
||||
# vscode
|
||||
.vscode/
|
2
LICENSE
|
@ -69,6 +69,8 @@ used during the build process and is not part of the compiled source code.
|
|||
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
||||
/esp32
|
||||
/ppp_set_auth.* (Apache-2.0)
|
||||
/rp2
|
||||
/mutex_extra.c (BSD-3-clause)
|
||||
/stm32
|
||||
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
||||
/stm32_it.* (MIT + BSD-3-clause)
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/>
|
||||
</p>
|
||||
|
||||
This is the MicroPython project, which aims to put an implementation
|
||||
of Python 3.x on microcontrollers and small embedded systems.
|
||||
You can find the official website at [micropython.org](http://www.micropython.org).
|
||||
|
||||
WARNING: this project is in beta stage and is subject to changes of the
|
||||
code-base, including project-wide name changes and API changes.
|
||||
|
||||
MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
||||
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
|
||||
Python 3.5 and some select features from later versions). The following core
|
||||
datatypes are provided: `str`(including basic Unicode support), `bytes`,
|
||||
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
|
||||
`collections.namedtuple`, classes and instances. Builtin modules include
|
||||
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
|
||||
`_thread` module (multithreading), `socket` and `ssl` for networking, and
|
||||
`asyncio`. Note that only a subset of Python 3 functionality is implemented
|
||||
for the data types and modules.
|
||||
|
||||
MicroPython can execute scripts in textual source form (.py files) or from
|
||||
precompiled bytecode (.mpy files), in both cases either from an on-device
|
||||
filesystem or "frozen" into the MicroPython executable.
|
||||
|
||||
MicroPython also provides a set of MicroPython-specific modules to access
|
||||
hardware-specific functionality and peripherals such as GPIO, Timers, ADC,
|
||||
DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
See the [online documentation](https://docs.micropython.org/) for API
|
||||
references and information about using MicroPython and information about how
|
||||
it is implemented.
|
||||
|
||||
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
|
||||
as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These
|
||||
are great places to ask questions and advice from the community or to discuss your
|
||||
MicroPython-based projects.
|
||||
|
||||
For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose)
|
||||
and follow the templates there.
|
||||
|
||||
For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features),
|
||||
the officially supported board from the
|
||||
[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers),
|
||||
see the [schematics and pinouts](http://github.com/micropython/pyboard) and
|
||||
[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html).
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
MicroPython is an open-source project and welcomes contributions. To be
|
||||
productive, please be sure to follow the
|
||||
[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines)
|
||||
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
|
||||
Note that MicroPython is licenced under the MIT license, and all contributions
|
||||
should follow this license.
|
||||
|
||||
About this repository
|
||||
---------------------
|
||||
|
||||
This repository contains the following components:
|
||||
- [py/](py/) -- the core Python implementation, including compiler, runtime, and
|
||||
core library.
|
||||
- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts
|
||||
into precompiled bytecode.
|
||||
- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on.
|
||||
- [lib/](lib/) -- submodules for external dependencies.
|
||||
- [tests/](tests/) -- test framework and test scripts.
|
||||
- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org).
|
||||
- [extmod/](extmod/) -- additional (non-core) modules implemented in C.
|
||||
- [tools/](tools/) -- various tools, including the pyboard.py module.
|
||||
- [examples/](examples/) -- a few example Python scripts.
|
||||
|
||||
"make" is used to build the components, or "gmake" on BSD-based systems.
|
||||
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
|
||||
(if your system only has Python 2.7 then invoke make with the additional option
|
||||
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
|
||||
|
||||
Supported platforms & architectures
|
||||
-----------------------------------
|
||||
|
||||
MicroPython runs on a wide range of microcontrollers, as well as on Unix-like
|
||||
(including Linux, BSD, macOS, WSL) and Windows systems.
|
||||
|
||||
Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although
|
||||
devices with at least 512kiB flash + 128kiB RAM allow a much more
|
||||
full-featured experience.
|
||||
|
||||
The [Unix](ports/unix) and [Windows](ports/windows) ports allow both
|
||||
development and testing of MicroPython itself, as well as providing
|
||||
lightweight alternative to CPython on these platforms (in particular on
|
||||
embedded Linux systems).
|
||||
|
||||
The ["minimal"](ports/minimal) port provides an example of a very basic
|
||||
MicroPython port and can be compiled as both a standalone Linux binary as
|
||||
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
|
||||
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
|
||||
is an example of the absolute minimum configuration, and is used to keep
|
||||
track of the code size of the core runtime and VM.
|
||||
|
||||
In addition, the following ports are provided in this repository:
|
||||
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
|
||||
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
|
||||
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
|
||||
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
|
||||
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
|
||||
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
|
||||
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
|
||||
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
|
||||
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
|
||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
||||
|
||||
The MicroPython cross-compiler, mpy-cross
|
||||
-----------------------------------------
|
||||
|
||||
Most ports require the [MicroPython cross-compiler](mpy-cross) to be built
|
||||
first. This program, called mpy-cross, is used to pre-compile Python scripts
|
||||
to .mpy files which can then be included (frozen) into the
|
||||
firmware/executable for a port. To build mpy-cross use:
|
||||
|
||||
$ cd mpy-cross
|
||||
$ make
|
||||
|
||||
External dependencies
|
||||
---------------------
|
||||
|
||||
The core MicroPython VM and runtime has no external dependencies, but a given
|
||||
port might depend on third-party drivers or vendor HALs. This repository
|
||||
includes [several submodules](lib/) linking to these external dependencies.
|
||||
Before compiling a given port, use
|
||||
|
||||
$ cd ports/name
|
||||
$ make submodules
|
||||
|
||||
to ensure that all required submodules are initialised.
|
190
README.md
|
@ -1,147 +1,87 @@
|
|||
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
|
||||
# PythonExtra - A community MicroPython for CASIO calculators
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/>
|
||||
</p>
|
||||
*Original MicroPython README: [`README-MicroPython.md`](README-MicroPython.md).*
|
||||
|
||||
This is the MicroPython project, which aims to put an implementation
|
||||
of Python 3.x on microcontrollers and small embedded systems.
|
||||
You can find the official website at [micropython.org](http://www.micropython.org).
|
||||
This is a MicroPython port for fx-CG 50, fx-9860G III and related CASIO calculators.
|
||||
|
||||
WARNING: this project is in beta stage and is subject to changes of the
|
||||
code-base, including project-wide name changes and API changes.
|
||||
**Build instructions**
|
||||
|
||||
MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
||||
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
|
||||
Python 3.5 and some select features from later versions). The following core
|
||||
datatypes are provided: `str`(including basic Unicode support), `bytes`,
|
||||
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
|
||||
`collections.namedtuple`, classes and instances. Builtin modules include
|
||||
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
|
||||
`_thread` module (multithreading), `socket` and `ssl` for networking, and
|
||||
`asyncio`. Note that only a subset of Python 3 functionality is implemented
|
||||
for the data types and modules.
|
||||
Requires the [fxSDK](/Lephenixnoir/fxsdk). Go to `ports/fxcg50` or `ports/fx9860g3` and run `make`. If it doesn't build, first try to use the `dev` branches for [fxSDK](/Lephenixnoir/fxSDK), [gint](/Lephenixnoir/gint), [fxlibc](/Lephenixnoir/fxlib) and [JustUI](/Lephenixnoir/JustUI). Rebuilds don't always work especially when checking out other commits (maybe my fault), so try to delete `build` if you think that's related.
|
||||
|
||||
MicroPython can execute scripts in textual source form (.py files) or from
|
||||
precompiled bytecode (.mpy files), in both cases either from an on-device
|
||||
filesystem or "frozen" into the MicroPython executable.
|
||||
Most of the code is in `ports/sh` and is shared between the platforms.
|
||||
|
||||
MicroPython also provides a set of MicroPython-specific modules to access
|
||||
hardware-specific functionality and peripherals such as GPIO, Timers, ADC,
|
||||
DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
|
||||
---
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
**Test suite**
|
||||
|
||||
See the [online documentation](https://docs.micropython.org/) for API
|
||||
references and information about using MicroPython and information about how
|
||||
it is implemented.
|
||||
Located in [`ports/sh/examples`](ports/sh/examples).
|
||||
|
||||
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
|
||||
as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These
|
||||
are great places to ask questions and advice from the community or to discuss your
|
||||
MicroPython-based projects.
|
||||
* **fx-CG**: Whether the program successfully runs on PythonExtra on
|
||||
models of the fx-CG family. This is typically tested on a Graph 90+E but
|
||||
should include the fx-CG 10/20/50.
|
||||
* **G-III**: Whether the program successfully runs on G-III models.
|
||||
This does **not** include older models like the fx-9860G II.
|
||||
* **Raw speedup**: Speedup from using PythonExtra instead of the official
|
||||
Python app, without changing the code (as a ratio of execution times).
|
||||
* **Full speedup**: Seedup from using PythonExtra-provided modules for
|
||||
rendering and input (usually `gint`), after changing the program's code.
|
||||
|
||||
For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose)
|
||||
and follow the templates there.
|
||||
| Program | fx-CG | G-III | Raw speedup | Full speedup |
|
||||
| ------- | ----- | ----- | ----------- | ------------ |
|
||||
| Chute tridimensionnelle | Yes | Yes | x1.36 | x2.26 ⁽¹⁾ |
|
||||
| Bad Apple | Meh⁽²⁾ | - | TODO | TODO |
|
||||
| Island of the Dead Kings | TODO | TODO | TODO | TODO |
|
||||
| Synchro-Donjon (AI mode) | Yes | TODO | x1.82 | - |
|
||||
| Flappy Bird | Yes | Yes | x1.04 | x2.35 |
|
||||
|
||||
For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features),
|
||||
the officially supported board from the
|
||||
[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers),
|
||||
see the [schematics and pinouts](http://github.com/micropython/pyboard) and
|
||||
[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html).
|
||||
⁽¹⁾ After upgrading to full-screen 396x224 instead of the original 120x80. (!)
|
||||
|
||||
Contributing
|
||||
------------
|
||||
⁽²⁾ Bad Apple requires unloading modules to not run out of memory, and I
|
||||
haven't been able to consistently do that. See the `unload-modules` branch.
|
||||
|
||||
MicroPython is an open-source project and welcomes contributions. To be
|
||||
productive, please be sure to follow the
|
||||
[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines)
|
||||
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
|
||||
Note that MicroPython is licenced under the MIT license, and all contributions
|
||||
should follow this license.
|
||||
---
|
||||
|
||||
About this repository
|
||||
---------------------
|
||||
**Basic benchmarks**
|
||||
|
||||
This repository contains the following components:
|
||||
- [py/](py/) -- the core Python implementation, including compiler, runtime, and
|
||||
core library.
|
||||
- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts
|
||||
into precompiled bytecode.
|
||||
- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on.
|
||||
- [lib/](lib/) -- submodules for external dependencies.
|
||||
- [tests/](tests/) -- test framework and test scripts.
|
||||
- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org).
|
||||
- [extmod/](extmod/) -- additional (non-core) modules implemented in C.
|
||||
- [tools/](tools/) -- various tools, including the pyboard.py module.
|
||||
- [examples/](examples/) -- a few example Python scripts.
|
||||
PythonExtra is slightly faster than the official Python app, probably due to
|
||||
optimization during compilation of the VM. The tests below show the effect on
|
||||
basic Python operations.
|
||||
|
||||
"make" is used to build the components, or "gmake" on BSD-based systems.
|
||||
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
|
||||
(if your system only has Python 2.7 then invoke make with the additional option
|
||||
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
|
||||
| Test | Program | Official Python (fx-CG 50) | PythonExtra (fx-CG 50) |
|
||||
| ---- | ------- | -------------------------- | ---------------------- |
|
||||
| VM speed | `pe_loop.py` (1 million `pass`) | ~12 seconds | 8.9 seconds |
|
||||
| Shell output | `pe_print.py` (print 100000 integers) | ~22 seconds | 11.3 seconds |
|
||||
| Large integers | `pe_fact.py` (compute 250!, 500 times) | ~15 seconds | 8.6 seconds |
|
||||
|
||||
Supported platforms & architectures
|
||||
-----------------------------------
|
||||
---
|
||||
|
||||
MicroPython runs on a wide range of microcontrollers, as well as on Unix-like
|
||||
(including Linux, BSD, macOS, WSL) and Windows systems.
|
||||
**TODO list**
|
||||
|
||||
Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although
|
||||
devices with at least 512kiB flash + 128kiB RAM allow a much more
|
||||
full-featured experience.
|
||||
Bugs to fix:
|
||||
- Fix not world switching during filesystem accesses (very unstable)
|
||||
- Fix current working directory not changing during a module import (for
|
||||
relative imports)
|
||||
- Fix casioplot not stopping on the last `show_screen()`
|
||||
|
||||
The [Unix](ports/unix) and [Windows](ports/windows) ports allow both
|
||||
development and testing of MicroPython itself, as well as providing
|
||||
lightweight alternative to CPython on these platforms (in particular on
|
||||
embedded Linux systems).
|
||||
Python features:
|
||||
- Compare features with existing implementations and other brands
|
||||
- Get filesystem access (open etc) with the POSIX interface
|
||||
- Get a decent amount of RAM not just the fixed 32 kiB that's hardcoded so far
|
||||
|
||||
The ["minimal"](ports/minimal) port provides an example of a very basic
|
||||
MicroPython port and can be compiled as both a standalone Linux binary as
|
||||
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
|
||||
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
|
||||
is an example of the absolute minimum configuration, and is used to keep
|
||||
track of the code size of the core runtime and VM.
|
||||
UI:
|
||||
- Add an option for fixed-width font which also sets $COLUMNS properly so that
|
||||
MicroPython paginates (requires better getenv/setenv support in fxlibc)
|
||||
- Use [unicode-fonts](/Lephenixnoir/unicode-fonts) to provide Unicode support
|
||||
* Extend it with a fixed-width uf8x9 which maybe changes some glyphs (like
|
||||
`i` and `l`; the usual fixed-width unambiguous styles)
|
||||
* Try and provide a font smaller than 5x7 for more compact shell on mono
|
||||
- A decent keymap that can input all relevant characters into the shell
|
||||
- Features that would match MicroPython's readline:
|
||||
* Multi-line input (figure out how to store it); also, auto-indent
|
||||
* History (use `MP_STATE_PORT(readline_hist)` with `readline_push_history()`
|
||||
for a start); also, zsh-style search
|
||||
* Autocompletion (use `mp_repl_autocomplete()` which should hook just fine)
|
||||
|
||||
In addition, the following ports are provided in this repository:
|
||||
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
|
||||
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
|
||||
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
|
||||
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
|
||||
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
|
||||
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
|
||||
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
|
||||
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
|
||||
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
|
||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
||||
|
||||
The MicroPython cross-compiler, mpy-cross
|
||||
-----------------------------------------
|
||||
|
||||
Most ports require the [MicroPython cross-compiler](mpy-cross) to be built
|
||||
first. This program, called mpy-cross, is used to pre-compile Python scripts
|
||||
to .mpy files which can then be included (frozen) into the
|
||||
firmware/executable for a port. To build mpy-cross use:
|
||||
|
||||
$ cd mpy-cross
|
||||
$ make
|
||||
|
||||
External dependencies
|
||||
---------------------
|
||||
|
||||
The core MicroPython VM and runtime has no external dependencies, but a given
|
||||
port might depend on third-party drivers or vendor HALs. This repository
|
||||
includes [several submodules](lib/) linking to these external dependencies.
|
||||
Before compiling a given port, use
|
||||
|
||||
$ cd ports/name
|
||||
$ make submodules
|
||||
|
||||
to ensure that all required submodules are initialised.
|
||||
Future wishes:
|
||||
- Build for fx-9860G II (requires manual filesystem support)
|
||||
- Lephe's secret ideas (complete previous list to unlock)
|
||||
|
|
|
@ -870,7 +870,7 @@ Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`.
|
|||
|
||||
The default devices at the board are:
|
||||
|
||||
- UART 1 at pins PB23/PB22, labelled RXD/TXD
|
||||
- UART 2 at pins PA13/PA12, labelled RXD/TXD
|
||||
- I2C 5 at pins PA22/PA23, labelled SDA/SCL
|
||||
- SPI 4 at pins PB12/PB11/PB13, labelled MOSI, MISO and SCK
|
||||
- DAC output on pins PA02 and PA05, labelled A0 and A4
|
||||
|
@ -884,36 +884,36 @@ The tables shown above were created with small a Python script running on the ta
|
|||
from machine import Pin
|
||||
import os
|
||||
|
||||
def print_entry(e, txt):
|
||||
def print_item(e, txt):
|
||||
print(txt, end=": ")
|
||||
if e == 255:
|
||||
print(" - ", end="")
|
||||
else:
|
||||
print("%d/%d" % (e >> 4, e & 0x0f), end="")
|
||||
|
||||
def print_pininfo(pin, info):
|
||||
print("%3d" % pin, end=" ")
|
||||
print("P%c%02d" % ("ABCD"[pin // 32], pin % 32), end="")
|
||||
print(" %12s" % info[0], end="")
|
||||
def print_pininfo(pin_id, name, info):
|
||||
|
||||
print("%3d" % pin_id, end=" ")
|
||||
print("%4s %12s" % (info[0], name), end="")
|
||||
print(" IRQ:%2s" % (info[1] if info[1] != 255 else "-"), end="")
|
||||
print(" ADC0:%2s" % (info[2] if info[2] != 255 else "-"), end="")
|
||||
if len(info) == 7:
|
||||
print_entry(info[3], " Serial1")
|
||||
print_entry(info[4], " Serial2")
|
||||
print_entry(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
|
||||
print_entry(info[6], " PWM2")
|
||||
print_item(info[3], " Serial1")
|
||||
print_item(info[4], " Serial2")
|
||||
print_item(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
|
||||
print_item(info[6], " PWM2")
|
||||
else:
|
||||
print(" ADC1:%2s" % (info[3] if info[3] != 255 else "-"), end="")
|
||||
print_entry(info[4], " Serial1")
|
||||
print_entry(info[5], " Serial2")
|
||||
print_entry(info[6], " TC")
|
||||
print_entry(info[7], " PWM1")
|
||||
print_entry(info[8], " PWM2")
|
||||
print_item(info[4], " Serial1")
|
||||
print_item(info[5], " Serial2")
|
||||
print_item(info[6], " TC")
|
||||
print_item(info[7], " PWM1")
|
||||
print_item(info[8], " PWM2")
|
||||
print()
|
||||
|
||||
def tblkey(i):
|
||||
name = i[1][0]
|
||||
if name != "-":
|
||||
name = i[1]
|
||||
if name != "":
|
||||
if len(name) < 3:
|
||||
return " " + name
|
||||
else:
|
||||
|
@ -921,17 +921,25 @@ The tables shown above were created with small a Python script running on the ta
|
|||
else:
|
||||
return "zzzzzzz%03d" % i[0]
|
||||
|
||||
def table(num = 127):
|
||||
def table(num=127, sort=True):
|
||||
pintbl = []
|
||||
inv_bd = {v: k for k, v in Pin.board.__dict__.items()}
|
||||
for i in range(num):
|
||||
try:
|
||||
pintbl.append((i, pininfo(i)))
|
||||
p = Pin(i)
|
||||
pi = pininfo(p)
|
||||
if p in inv_bd.keys():
|
||||
name = inv_bd[p]
|
||||
else:
|
||||
name = ""
|
||||
pintbl.append((i, name, pininfo(i)))
|
||||
except:
|
||||
pass
|
||||
# print("not defined")
|
||||
|
||||
pintbl.sort(key=tblkey)
|
||||
if sort:
|
||||
pintbl.sort(key=tblkey)
|
||||
for item in pintbl:
|
||||
print_pininfo(item[0], item[1])
|
||||
print_pininfo(item[0], item[1], item[2])
|
||||
|
||||
table()
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
# Using Numworks' modules `kandinsky`, `ion` and `time` with PythonExtra
|
||||
|
||||
PythonExtra offers the possibility of using certain Numworks modules in order to make the scripts of this machine compatible as is on Casio fx-CG50 (no support on the fx9860G due to insufficient memory and lack of color screen ).
|
||||
|
||||
This is a Work in Progress (WIP) and the support is subject to extensive testing at this stage. The port concerns the Numworks `kandinsky`, `ion` and `time` modules which are machine specific and are now supported via this implementation. The `math`, `cmath`, `random` modules being identical between the `Numworks` version and the `builtins` modules of MicroPython, they are therefore not part of this implementation but are perfectly usable without modification in the scripts.
|
||||
|
||||
Note: the `turtle` and `matplotlib.pyplot` modules are not included in this implementation. It is possible to use the `turtle`, `matplotlib` and `casioplot` modules from Casio Education which are perfectly functional and provided as an example in `ports/sh/examples`.
|
||||
|
||||
|
||||
## `kandinsky`
|
||||
|
||||
The `kandinsky` module provides support for graphics primitives via high-performance `gint` routines. All the functions of this module are available:
|
||||
|
||||
- `color(r,g,b)`: Generates the value of the color r,g,b. You can also simply use a tuple to define a color: (r,g,b).
|
||||
|
||||
- `get_pixel(x,y)`: Returns the color of the pixel at x,y coordinates as a tuple (r,g,b).
|
||||
|
||||
- `set_pixel(x,y,color)`: Lights the pixel x,y of the color color.
|
||||
|
||||
- `draw_string(text,x,y,[color1],[color2])`: Displays the text at x,y coordinates. The arguments color1 (text color) and color2 (text background color) are optional.
|
||||
|
||||
- `fill_rect(x,y,width,height,color)`: Fills a rectangle of width width and height height with the color color at the point of x and y coordinates.
|
||||
|
||||
The module also offers a certain number of colors explicitly named and accessible by a character string. The following values can be used instead of the color parameters of the `kandinsky` functions:
|
||||
- "red", "r"
|
||||
- "green", "g"
|
||||
- "blue", "b"
|
||||
- "black", "k"
|
||||
- "white", "w"
|
||||
- "yellow", "y"
|
||||
- "pink"
|
||||
- "magenta"
|
||||
- "grey", "gray"
|
||||
- "purple"
|
||||
- "orange"
|
||||
- "cyan"
|
||||
- "brown"
|
||||
|
||||
The following functions are additions to take advantage of the wide screen of the fxCG and are therefore an extension of the `Kandinsky` module. They are therefore by definition not compatible with Python Numwork. These functions can be recognized by their names which all begin with `CGEXT_`:
|
||||
|
||||
- `CGEXT_Enable_Wide_Screen()`: Enables the fxCG wide screen, no settings are necessary. The x-coordinates of the physical screen can be negative to encroach on the left white stripe and greater than 319 pixels to encroach on the right white stripe;
|
||||
|
||||
- `CGEXT_Disable_Wide_Screen()`: Cancels the activation of the fxCG extended screen, no settings are necessary. The x coordinates of the physical screen will be constrained between 0 and 320 pixels. Beyond that, the route will not be carried out.
|
||||
|
||||
- `CGEXT_Is_Wide_Screen_Enabled()`: Returns `True` if the extended screen is active and `False` otherwise.
|
||||
|
||||
- `CGEXT_Set_Margin_Color( color )` : Paints the margin of the `Numworks` screen on fxCG with the specified color.
|
||||
|
||||
Note 1: after having made a plot in the extended area, it must be active to allow its deletion (typically via a call to the `fill_rect()` function with the appropriate parameters).
|
||||
|
||||
Note 2: In non-extended mode (by default when initializing the `Kandinsky` module) the screen coordinates go from (0,0) to (319,221) centered on the fxCG screen. In extended mode, the screen coordinates range from (-38,-1) to (358,223).
|
||||
|
||||
|
||||
## `ion`
|
||||
|
||||
The `ion` module gives access to the `keydown(k)` function which returns True if the key k placed as an argument is pressed and False otherwise.
|
||||
|
||||
The “conversion” of the keys between the Numworks machine and Casio fxCG50 is done according to the following mapping:
|
||||
|
||||
| Numworks | Casio fxCG50 | Numworks Key # |
|
||||
|----------|--------------|---------------------|
|
||||
| KEY_LEFT | KEY_LEFT | 0 |
|
||||
| KEY_UP | KEY_UP | 1 |
|
||||
| KEY_DOWN | KEY_DOWN | 2 |
|
||||
| KEY_RIGHT | KEY_RIGHT | 2 |
|
||||
| KEY_OK | KEY_F1 | 4 |
|
||||
| KEY_BACK | KEY_EXIT | 5 |
|
||||
| KEY_HOME | KEY_MENU | 6 |
|
||||
| KEY_ONOFF | KEY_ACON | 7 |
|
||||
| ... | ... | ... |
|
||||
| KEY_SHIFT | KEY_SHIFT | 12 |
|
||||
| KEY_ALPHA | KEY_ALPHA | 13 |
|
||||
| KEY_XNT | KEY_XOT | 14 |
|
||||
| KEY_VAR | KEY_VARS | 15 |
|
||||
| KEY_TOOLBOX | KEY_OPTN | 16 |
|
||||
| KEY_BACKSPACE | KEY_DEL | 17 |
|
||||
| KEY_EXP | KEY_EXP | 17 |
|
||||
| KEY_LN | KEY_LN | 19 |
|
||||
| KEY_LOG | KEY_LOG | 20 |
|
||||
| KEY_IMAGINARY | KEY_F2 | 21 |
|
||||
| KEY_COMMA | KEY_COMMA | 22 |
|
||||
| KEY_POWER | KEY_POWER | 23 |
|
||||
| KEY_SINE | KEY_SIN | 24 |
|
||||
| KEY_COSINE | KEY_COS | 25 |
|
||||
| KEY_TANGENT | KEY_TAN | 26 |
|
||||
| KEY_PI | KEY_F3 | 27 |
|
||||
| KEY_SQRT | KEY_F4 | 28 |
|
||||
| KEY_SQUARE | KEY_SQUARE | 29 |
|
||||
| KEY_SEVEN | KEY_7 | 30 |
|
||||
| KEY_EIGHT | KEY_8 | 31 |
|
||||
| KEY_NINE | KEY_9 | 32 |
|
||||
| KEY_LEFTPARENTHESIS | KEY_LEFTP | 33 |
|
||||
| KEY_RIGHTPARENTHESIS | KEY_RIGHTP | 34 |
|
||||
| ... | ... | ... |
|
||||
| KEY_FOUR | KEY_4 | 36 |
|
||||
| KEY_FIVE | KEY_5 | 37 |
|
||||
| KEY_SIX | KEY_6 | 38 |
|
||||
| KEY_MULTIPLICATION | KEY_MUL | 39 |
|
||||
| KEY_DIVISION | KEY_DIV | 40 |
|
||||
| ... | ... | ... |
|
||||
| KEY_ONE | KEY_1 | 42 |
|
||||
| KEY_TWO | KEY_2 | 43 |
|
||||
| KEY_THREE | KEY_3 | 44 |
|
||||
| KEY_PLUS | KEY_ADD | 45 |
|
||||
| KEY_MINUS | KEY_SUB | 46 |
|
||||
| ... | ... | ... |
|
||||
| KEY_ZERO | KEY_0 | 48 |
|
||||
| KEY_DOT | KEY_DOT | 49 |
|
||||
| KEY_EE | KEY_F5 | 50 |
|
||||
| KEY_ANS | KEY_NEG | 51 |
|
||||
| KEY_EXE | KEY_EXE | 52 |
|
||||
|
||||
|
||||
## `time`
|
||||
|
||||
The `time` module gives access to two functions:
|
||||
|
||||
- `monotonic()`: Returns the clock value at the time the function is called.
|
||||
|
||||
- `sleep(t)`: Suspends execution for t seconds.
|
|
@ -0,0 +1,120 @@
|
|||
# Utilisation des modules `kandinsky`, `ion` et `time` de l'implémentation Python `Numworks`
|
||||
|
||||
PythonExtra offre la possibilité d'utiliser certains modules de la Numworks afin de rendre les scripts de cette machine compatible en l'état sur Casio fx-CG50 (pas de support sur la fx9860G pour cause de mémoire insuffisante et d'abence d'écran couleur).
|
||||
|
||||
Il s'agit d'un Work in Progress (WIP) et le support est sujet à tests approfondis à ce stade. Le port concerne les modules `kandinsky`, `ion` et `time` de la Numworks qui sont spécifiques à la machine et sont désormais supportés via cette implémentation. Les modules `math`, `cmath`, `random` étant identiques entre la version `Numworks` et les modules `builtins` de MicroPython, ils ne font donc pas partie de cette implémentation mais sont parfaitement utilisables sans modification dans les scripts.
|
||||
|
||||
Note : les modules `turtle` et `matplotlib.pyplot` ne sont pas repris dans cette implémentation. Il est possible d'utiliser les modules `turtle`, `matplotlib` et `casioplot` de Casio Education qui sont parfaitement fonctionnels et fournis en example dans `ports/sh/examples`.
|
||||
|
||||
|
||||
## `kandinsky`
|
||||
|
||||
Le module `kandinsky` offre le support des primitives graphiques via les routines hautes performance de `gint`. Toutes les fonctions de ce module sont disponibles :
|
||||
|
||||
- `color(r,g,b)` : Génère la valeur de la couleur r,g,b. Vous pouvez aussi simplement utiliser un tuple pour définir une couleur : (r,g,b).
|
||||
|
||||
- `get_pixel(x,y)` : Renvoie la couleur du pixel aux coordonnées x,y sous forme de tuple (r,g,b).
|
||||
|
||||
- `set_pixel(x,y,color)` : Allume le pixel x,y de la couleur color.
|
||||
|
||||
- `draw_string(text,x,y,[color1],[color2])` : Affiche le texte text aux coordonnées x,y. Les arguments color1 (couleur du texte) et color2 (couleur de lʼarrière plan du texte) sont optionnels.
|
||||
|
||||
- `fill_rect(x,y,width,height,color)` : Remplit un rectangle de largeur width et de hauteur height avec la couleur color au point de coordonnées x et y.
|
||||
|
||||
Le module offre de plus un certain nombre de couleurs explicitement nommées et accessibles par une chaine de caractères. Les valeurs suivantes sont utilisables en lieu et place des paramètres de couleur des fonctions de `kandinsky` :
|
||||
- "red", "r"
|
||||
- "green", "g"
|
||||
- "blue", "b"
|
||||
- "black", "k"
|
||||
- "white", "w"
|
||||
- "yellow", "y"
|
||||
- "pink"
|
||||
- "magenta"
|
||||
- "grey", "gray"
|
||||
- "purple"
|
||||
- "orange"
|
||||
- "cyan"
|
||||
- "brown"
|
||||
|
||||
Les fonctions suivantes sont des ajouts pour tirer partie de l'écran large de la fxCG et qui sont donc une extension du module `Kandinsky`. Elles ne sont donc par définition pas compatible avec le Python Numwork. Ces fonctions sont reconnaisables à leurs appellations qui commencent toutes par `CGEXT_` :
|
||||
|
||||
- `CGEXT_Enable_Wide_Screen()` : Active l'écran étendu de la fxCG, aucun paramètre n'est nécessaire. Les coordonnées x de l'écran physique peuvent être négatives pour empiéter sur la bande blanche de gauche et supérieures à 319 pixels pour empièter sur la bande blanche de droite;
|
||||
|
||||
- `CGEXT_Disable_Wide_Screen()` : Annule l'activation de l'écran étendu de la fxCG, aucun paramètre n'est nécessaire. Les coordonnées x de l'écran physique seront contraintes entre 0 et 320 pixels. Au-delà, le tracé ne sera pas effectué.
|
||||
|
||||
- `CGEXT_Is_Wide_Screen_Enabled()` : Retourne `True` si l'écran étendu est actif et `False` dans le cas contraire.
|
||||
|
||||
- `CGEXT_Set_Margin_Color( color )` : Trace les marge de la fxCG50 (pourtours de l'écran `Numworks`) de la couleur passée en argument.
|
||||
|
||||
Note 1 : après avoir réalisé un tracé dans la zone étendue, il faut que celle-ci soit active pour permettre son effacement (typiquement via un appel à la fonction `fill_rect()` avec les paramètres adéquats).
|
||||
|
||||
Note 2 : En mode non étendu (par défaut à l'initialisation du module `Kandinsky`) les coordonnées de l'écran vont de (0,0) à (319,221) centré sur l'écran de la fxCG. En mode étendu, les coordonnées de l'écran vont de (-38,-1) à (358,223).
|
||||
|
||||
|
||||
## `ion`
|
||||
|
||||
Le module `ion` donne accès à la fonction `keydown(k)` qui renvoie True si la touche k placée en argument est appuyée et False sinon.
|
||||
|
||||
La "conversion" des touches entre la machine Numworks et Casio fxCG50 se fait selon le mapping suivant :
|
||||
|
||||
| Numworks | Casio fxCG50 | Numworks Key # |
|
||||
|----------|--------------|---------------------|
|
||||
| KEY_LEFT | KEY_LEFT | 0 |
|
||||
| KEY_UP | KEY_UP | 1 |
|
||||
| KEY_DOWN | KEY_DOWN | 2 |
|
||||
| KEY_RIGHT | KEY_RIGHT | 2 |
|
||||
| KEY_OK | KEY_F1 | 4 |
|
||||
| KEY_BACK | KEY_EXIT | 5 |
|
||||
| KEY_HOME | KEY_MENU | 6 |
|
||||
| KEY_ONOFF | KEY_ACON | 7 |
|
||||
| ... | ... | ... |
|
||||
| KEY_SHIFT | KEY_SHIFT | 12 |
|
||||
| KEY_ALPHA | KEY_ALPHA | 13 |
|
||||
| KEY_XNT | KEY_XOT | 14 |
|
||||
| KEY_VAR | KEY_VARS | 15 |
|
||||
| KEY_TOOLBOX | KEY_OPTN | 16 |
|
||||
| KEY_BACKSPACE | KEY_DEL | 17 |
|
||||
| KEY_EXP | KEY_EXP | 17 |
|
||||
| KEY_LN | KEY_LN | 19 |
|
||||
| KEY_LOG | KEY_LOG | 20 |
|
||||
| KEY_IMAGINARY | KEY_F2 | 21 |
|
||||
| KEY_COMMA | KEY_COMMA | 22 |
|
||||
| KEY_POWER | KEY_POWER | 23 |
|
||||
| KEY_SINE | KEY_SIN | 24 |
|
||||
| KEY_COSINE | KEY_COS | 25 |
|
||||
| KEY_TANGENT | KEY_TAN | 26 |
|
||||
| KEY_PI | KEY_F3 | 27 |
|
||||
| KEY_SQRT | KEY_F4 | 28 |
|
||||
| KEY_SQUARE | KEY_SQUARE | 29 |
|
||||
| KEY_SEVEN | KEY_7 | 30 |
|
||||
| KEY_EIGHT | KEY_8 | 31 |
|
||||
| KEY_NINE | KEY_9 | 32 |
|
||||
| KEY_LEFTPARENTHESIS | KEY_LEFTP | 33 |
|
||||
| KEY_RIGHTPARENTHESIS | KEY_RIGHTP | 34 |
|
||||
| ... | ... | ... |
|
||||
| KEY_FOUR | KEY_4 | 36 |
|
||||
| KEY_FIVE | KEY_5 | 37 |
|
||||
| KEY_SIX | KEY_6 | 38 |
|
||||
| KEY_MULTIPLICATION | KEY_MUL | 39 |
|
||||
| KEY_DIVISION | KEY_DIV | 40 |
|
||||
| ... | ... | ... |
|
||||
| KEY_ONE | KEY_1 | 42 |
|
||||
| KEY_TWO | KEY_2 | 43 |
|
||||
| KEY_THREE | KEY_3 | 44 |
|
||||
| KEY_PLUS | KEY_ADD | 45 |
|
||||
| KEY_MINUS | KEY_SUB | 46 |
|
||||
| ... | ... | ... |
|
||||
| KEY_ZERO | KEY_0 | 48 |
|
||||
| KEY_DOT | KEY_DOT | 49 |
|
||||
| KEY_EE | KEY_F5 | 50 |
|
||||
| KEY_ANS | KEY_NEG | 51 |
|
||||
| KEY_EXE | KEY_EXE | 52 |
|
||||
|
||||
|
||||
## `time`
|
||||
|
||||
Le module `time` donne accès à deux fonctions :
|
||||
|
||||
- `monotonic()` : Renvoie la valeur de lʼhorloge au moment où la fonction est appelée.
|
||||
|
||||
- `sleep(t)` : Suspend lʼexécution pendant t secondes.
|
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1,53 @@
|
|||
# `casioplot`: CASIO's official I/O module
|
||||
|
||||
`casioplot` is a drawing library provided by CASIO as support for the official `turtle` and `matplotlib` modules. It was [announced in February 2020](https://www.planet-casio.com/Fr/forums/topic16154-1-modules-graphiques-python-en-avril-matplotlib-et-turtle.html) and [released in April](https://www.planet-casio.com/Fr/forums/topic16243-1-rendu-graphique-en-python-partie-1-decouverte-de-matplotlib-et-turtle.html). The module is notably available on G-III and fx-CG models with the same API. As of March 2024, `casioplot` is the only custom module in CASIO's official port of MicroPython. PythonExtra also provides the module for source compatibility.
|
||||
|
||||
```py
|
||||
import casioplot
|
||||
# or
|
||||
from casioplot import *
|
||||
```
|
||||
|
||||
**Contents**
|
||||
- [Rendering functions](#rendering-functions)
|
||||
- [Considerations for rendering](#considerations-for-rendering)
|
||||
- [Differences with the official `casioplot` module](#differences-with-the-official-casioplot-module)
|
||||
|
||||
## Rendering functions
|
||||
|
||||
```py
|
||||
show_screen() -> None
|
||||
clear_screen() -> None
|
||||
set_pixel(x: int, y: int, ?color: (int, int, int)) -> None
|
||||
get_pixel(x: int, y: int) -> (int, int, int)
|
||||
draw_string(x: int, y: int, text: str, ?color: (int, int, int), ?size: str) -> None
|
||||
```
|
||||
|
||||
The rendering area is of size 128x64 on G-III and 384x216 on fx-CG. While the G-III supports only two colors (black and white), the fx-CG supports 65536 colors (16-bit RGB565). Still, the color format is _always_ (r,g,b) triplets with 0 ≤ r,g,b ≤ 255. This helps compatibility between models and with PC, at a performance cost. Calculators process these colors by _approximating_ them to the closest color they can represent.
|
||||
|
||||
Like the gint module, `casioplot` functions draw to an internal buffer called the VRAM, and the module only pushes that to the screen when explicitly asked to or at the end of the program.
|
||||
|
||||
`show_screen()` pushes the VRAM to screen after something has been drawn.
|
||||
|
||||
`clear_screen()` fills the VRAM in white.
|
||||
|
||||
`set_pixel()` changes the color of the pixel at (x,y) into the provided `color` encoded as an (r,g,b) triplet (black if not provided). Building triplets is a bit slow so don't write something like `set_pixel(x, y, (0,0,0))` in a loop, store the triplet in a variable and use that instead.
|
||||
|
||||
`get_pixel()` returns the color of the pixel at (x,y) in VRAM as an (r,g,b) triplet. Because VRAM stores colors in the same format as the display, which typically doesn't support all 16 million colors, `get_pixel()` immediately after `set_pixel()`usually returns an _approximation_ of the original color. Because it allocates a triplet, this function is also excruciatingly slow to call in a loop, to the point of creating GC-driven lag spikes that in some situations make it completely unusable.
|
||||
|
||||
`draw_string()` draws text. (x,y) is the location of the top-left corner of the rendered string. The text color is optional; if specified it should be an (r,g,b) triplet, otherwise it is black. The font size can be either of the strings `"small"`, `"medium"` or `"large"` and defaults to medium. On the G-III, the font sizes `"small"` and `"medium"` are identical, but on the fx-CG all three fonts are different. Any `'\n'` in the string is replaced with spaces when drawing.
|
||||
|
||||
TODO: Example
|
||||
|
||||
## Considerations for rendering
|
||||
|
||||
_Text mode._ `casioplot` automatically switches PythonExtra into graphics mode when imported. Programs that want to render graphics frames after a `print()` should `show_screen()` _before_ rendering the first frame since `print()` switches to text mode.
|
||||
|
||||
_Performance._ Writing to VRAM is the main reason why rendering in `casioplot` is sometimes much faster than in Basic. Basic pushes the rendered data to the display after every call, which is slow. Unfortunately, `casioplot` ends up losing for complex drawing tasks for which Basic has complex functions (like DrawStat) while `casioplot` just has single pixels. In this case, functions from the [gint module](modgint-en.md) can be of help.
|
||||
|
||||
## Differences with the official `casioplot` module
|
||||
|
||||
- PythonExtra's implementation doesn't automatically show the screen when the program finishes executing.
|
||||
- The fonts for `draw_string()` are not identical on the G-III port.
|
||||
- The fonts for `draw_string()` currently only support ASCII.
|
||||
- The drawable space on fx-CG is at the top left section of the screen.
|
|
@ -0,0 +1,53 @@
|
|||
# `casioplot` : Module officiel d'I/O de CASIO
|
||||
|
||||
`casioplot` est une bibliothèque de dessin fournie par CASIO pour supporter les modules officiels `turtle` et `matplotlib`. Le module a été [annoncé en Février 2020](https://www.planet-casio.com/Fr/forums/topic16154-1-modules-graphiques-python-en-avril-matplotlib-et-turtle.html) et [publié en Avril](https://www.planet-casio.com/Fr/forums/topic16243-1-rendu-graphique-en-python-partie-1-decouverte-de-matplotlib-et-turtle.html). Le module est disponible sur Graph 35+E II et Graph 90+E avec la même API. C'est le seul module personnalisé dans le port MicroPython de CASIO (à date de Mars 2024). PythonExtra fournit le module par compatibilité pour les scripts officiels.
|
||||
|
||||
```py
|
||||
import casioplot
|
||||
# or
|
||||
from casioplot import *
|
||||
```
|
||||
|
||||
**Sommaire**
|
||||
- [Fonctions de dessin](#fonctions-de-dessin)
|
||||
- [Considérations spéciales pour le rendu](#considérations-spéciales-pour-le-rendu)
|
||||
- [Différences avec le module `casioplot` officiel](#différences-avec-le-module-casioplot-officiel)
|
||||
|
||||
## Fonctions de dessin
|
||||
|
||||
```py
|
||||
show_screen() -> None
|
||||
clear_screen() -> None
|
||||
set_pixel(x: int, y: int, ?color: (int, int, int)) -> None
|
||||
get_pixel(x: int, y: int) -> (int, int, int)
|
||||
draw_string(x: int, y: int, text: str, ?color: (int, int, int), ?size: str) -> None
|
||||
```
|
||||
|
||||
La zone de dessin est de 128x64 pixels sur Graph 35+E II et 384x216 pixels sur la Graph 90+E. La Graph 35+E II ne supporte que deux couleurs (noir et blanc) tandis que la Graph 90+E peut afficher 65536 couleurs (RGB565 16 bits). Cependant, le format de couleurs est _quand même_ des triplets (r,g,b) avec 0 ≤ r,g,b ≤ 255. Ce choix maintient la compabilité entre les modèles et avec le PC, en échange d'un coût en performance. Les calculatrices approximent ces couleurs en les remplaçant par la couleur la plus proche qu'elles peuvent afficher.
|
||||
|
||||
Comme le module gint, `casioplot` dessine systématiquement dans un buffer interne qu'on appelle la VRAM, et n'affiche le résultat à l'écran que quand on lui demande explicitement, ou à la fin de l'exécution.
|
||||
|
||||
`show_screen()` affiche à l'écran les contenus de la VRAM après un dessin.
|
||||
|
||||
`clear_screen()` remplit la VRAM en blanc.
|
||||
|
||||
`set_pixel()` remplace la couleur du pixel à la position (x,y) par `color`, qui doit être un triplet (r,g,b) si fournie, et sera noir si absente. Construire des triplets est un peu lent donc il vaut mieux éviter d'écrire des appels comme `set_pixel(x, y, (0,0,0))` dans des boucles ; il est plus performant de stocker le triplet dans une variable et d'utiliser la variable.
|
||||
|
||||
`get_pixel()` renvoie la couleur du pixel à la position (x,y) de la VRAM sous la forme d'un triplet (r,g,b). Comme la VRAM stocke les couleurs au même format que l'écran, qui ne supporte généralement pas 16 millions de couleurs, appeler `get_pixel()` juste après `set_pixel()` renvoie une _approximation_ de la couleur originale. Comme cette fonction alloue un triplet, elle est atrocement lente à appeler en boucle, au point où elle peut créer du lag simplement par sa pression sur le GC, ce qui la rend parfois inutilisable.
|
||||
|
||||
`draw_string()` affiche du texte. (x,y) est la position du coin haut-gauche du rectangle dans lequel le texte est dessiné. La couleur est optionnelle ; si elle est spécifiée il faut que ce soit un triplet (r,g,b), sinon c'est noir. La taille peut être l'une des trois chaînes `"small"`, `"medium"` ou `"large"` ; la valeur par défaut est `"medium"`. Sur la Graph 35+E II, les polices `"small"` et `"medium"` sont identiques, tandis que sur la Graph 90+E les trois polices sont différentes. Tout `'\n'` dans la chaîne est remplacé par un espace avant d'afficher.
|
||||
|
||||
TODO: Exemple
|
||||
|
||||
## Considérations spéciales pour le rendu
|
||||
|
||||
_Mode texte._ `casioplot` passe automatiquement PythonExtra en mode graphique à l'import. Les programmes qui veulent faire du dessin graphique après un `print()` doivent appeler `show_screen()` _avant_ de commencer à dessiner le premier frame parce que `print()` repasse en mode texte.
|
||||
|
||||
_Performance._ Le fait que les fonctions de dessin écrivent silencieusement dans la VRAM est la principale raison pour laquelle `casioplot` est parfois beaucoup plus rapide que le dessin en Basic. PRGM réaffiche la VRAM à l'écran après chaque appel d'une fonction de dessin, ce qui est lent. Malheureusement, `casioplot` redevient plus lent que le Basic pour les dessins complexes pour lesquels il y a des fonctions spécialisées en Basic (comme `DrawStat`), puisque `casioplot` ne peut dessiner qu'un pixel à la fois. Dans ces situations, il vaut mieux utiliser les fonctions de dessin du [module gint](modgint-fr.md).
|
||||
|
||||
## Différences avec le module `casioplot` officiel
|
||||
|
||||
- L'implémentation PythonExtra du module n'affiche pas automatiquement l'écran à la fin du programme.
|
||||
- Les polices pour `draw_string()` diffèrent des polices officielles sur Graph 35+E II.
|
||||
- Les polices pour `draw_string()` ne supportent actuellement que les caractères ASCII.
|
||||
- Les zone de dessin sur Graph 90+E est en haut à gauche de l'écran.
|
|
@ -0,0 +1,433 @@
|
|||
# `gint`: Wrapper for the gint library
|
||||
|
||||
PythonExtra is developed with the [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) and uses the [gint kernel](https://gitea.planet-casio.com/Lephenixnoir/gint) as a runtime. The Python module `gint` provides access to gint's internal functions for rendering, keyboard, and more. Since gint has many versatile functions with good performance, it is beneficial to use it instead of e.g. `casioplot` or `turtle`.
|
||||
|
||||
The `gint` module tries to match its API with the original API of the C library, which is why few functions use keyword arguments or overloading. There are a few differences documented at the end of this document. For details not described in this document, one can refer to [gint's header files](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint) which are always applicable unless this document explicitly says otherwise.
|
||||
|
||||
All constants, functions, etc. discussed here are in the `gint` module.
|
||||
|
||||
```py
|
||||
import gint
|
||||
# or:
|
||||
from gint import *
|
||||
```
|
||||
|
||||
**Contents**
|
||||
- [Keyboard input](#keyboard-input)
|
||||
- [Drawing and rendering](#drawing-and-rendering)
|
||||
- [Differences with gint's C API](#differences-with-gints-c-api)
|
||||
|
||||
## Keyboard input
|
||||
|
||||
Reference headers: [`<gint/keyboard.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keyboard.h) and [`<gint/keycodes.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keycodes.h).
|
||||
|
||||
The module provides integer constants to refer to keyboard keys, with the following names:
|
||||
|
||||
| | | | | | |
|
||||
|------------|------------|------------|------------|------------|-------------|
|
||||
|`KEY_F1` |`KEY_F2` |`KEY_F3` |`KEY_F4` |`KEY_F5` |`KEY_F6` |
|
||||
|`KEY_SHIFT` |`KEY_OPTN` |`KEY_VARS` |`KEY_MENU` |`KEY_LEFT` |`KEY_UP` |
|
||||
|`KEY_ALPHA` |`KEY_SQUARE`|`KEY_POWER` |`KEY_EXIT` |`KEY_DOWN` |`KEY_RIGHT` |
|
||||
|`KEY_XOT` |`KEY_LOG` |`KEY_LN` |`KEY_SIN` |`KEY_COS` |`KEY_TAN` |
|
||||
|`KEY_FRAC` |`KEY_FD` |`KEY_LEFTP` |`KEY_RIGHTP`|`KEY_COMMA` |`KEY_ARROW` |
|
||||
|`KEY_7` |`KEY_8` |`KEY_9` |`KEY_DEL` |`KEY_ACON` | |
|
||||
|`KEY_4` |`KEY_5` |`KEY_6` |`KEY_MUL` |`KEY_DIV` | |
|
||||
|`KEY_1` |`KEY_2` |`KEY_3` |`KEY_ADD` |`KEY_SUB` | |
|
||||
|`KEY_0` |`KEY_DOT` |`KEY_EXP` |`KEY_NEG` |`KEY_EXE` | |
|
||||
|
||||
### Keyboard events
|
||||
|
||||
```
|
||||
key_event:
|
||||
.time -> int
|
||||
.mod -> bool
|
||||
.shift -> bool
|
||||
.alpha -> bool
|
||||
.type -> KEYEV_NONE | KEYEV_DOWN | KEYEV_UP | KEYEV_HOLD
|
||||
.key -> KEY_*
|
||||
```
|
||||
|
||||
gint communicates information about keyboard activity through _events_. Events indicate when a key (`.key` field) is pressed, repeated or released (`.type` field equal to `KEYEV_DOWN`, `KEYEV_HOLD` and `KEYEV_UP` respectively), when (`.time` field), and whether modifiers (SHIFT, `.shift` field, and ALPHA, `.alpha` field) where active at that time.
|
||||
|
||||
(The `.mod` field isn't very interesting, and the `KEYEV_NONE` value for the `.type` field is discussed later with `pollevent()`.)
|
||||
|
||||
The functions `getkey()`, `getkey_opt()`, `pollevent()` and `waitevent()` all return events.
|
||||
|
||||
### Waiting for a key press
|
||||
|
||||
```py
|
||||
getkey() -> key_event
|
||||
getkey_opt(opts: GETKEY_*, timeout_ms: int | None) -> key_event
|
||||
```
|
||||
|
||||
The function `getkey()` pauses the program until a key is pressed or repeated, and returns the associated event (which is always of type `KEYEV_DOWN` or `KEYEV_HOLD`). By default, only arrow keys are repeated, once after 400 ms, then every 40 ms.
|
||||
|
||||
A few things can happen while `getkey()` is waiting. The user can press SHIFT or ALPHA which will trigger modifiers and affect the `.shift` and `.alpha` fields of the returned event. The user can also go to the main menu by pressing MENU or turn the calculator off with SHIFT+AC/ON.
|
||||
|
||||
_Example._ In a selection menu with N possible items, one could navigate with the up and down arrow keys, jump to the top or bottom with SHIFT up and SHIFT down, and validate with EXE.
|
||||
|
||||
```py
|
||||
ev = getkey()
|
||||
if ev.key == KEY_EXE:
|
||||
pass # Validate
|
||||
elif ev.key == KEY_UP and ev.shift:
|
||||
pos = 0 # Jump to top
|
||||
elif ev.key == KEY_DOWN and ev.shift:
|
||||
pos = N-1 # Jump to bottom
|
||||
elif ev.key == KEY_UP and pos > 0:
|
||||
pos -= 1 # Move one place up
|
||||
elif ev.key == KEY_DOWN and pos < N-1:
|
||||
pos += 1 # Move one place down
|
||||
```
|
||||
|
||||
The function `getkey_opt()` generalizes `getkey()` and provides more options to customize its behavior. The `opts` parameter accepts a combination (sum) of options from the table below, and the parameter `timeout_ms`, when not `None`, specifies how long `getkey_opt()` should wait before returning a `KEYEV_NONE` event if nothing happens. The delay is specified in milliseconds but the actual resolution is about 7-8 ms.
|
||||
|
||||
| Option | `getkey()` | Description |
|
||||
|------------------------|------------|--------------------------------------------------|
|
||||
| `GETKEY_MOD_SHIFT` | Yes | SHIFT is a modifier key |
|
||||
| `GETKEY_MOD_ALPHA` | Yes | ALPHA is a modifier key |
|
||||
| `GETKEY_BACKLIGHT` | Yes | SHIFT+OPTN toggles display backlight |
|
||||
| `GETKEY_MENU` | Yes | MENU brings up the calculator's main menu |
|
||||
| `GETKEY_REP_ARROWS` | Yes | Repeats arrow keys when held |
|
||||
| `GETKEY_REP_ALL` | No | Repeats all keys when held |
|
||||
| `GETKEY_REP_PROFILE` | Yes* | Enable custom repeat delays |
|
||||
| `GETKEY_FEATURES` | Yes* | Enable custom global shortcuts |
|
||||
| `GETKEY_MENU_DUPDATE` | Yes | Update display after return to menu (fx-CG) |
|
||||
| `GETKEY_MENU_EVENT` | No | Send a `KEYEV_OSMENU` event after return to menu |
|
||||
| `GETKEY_POWEROFF` | Yes | SHIFT+AC/ON turns the calculator off |
|
||||
|
||||
`getkey()` is equivalent to `getkey_opt(opts, None)` where `opts` is the sum of all options that have "Yes" in the `getkey()` column above.
|
||||
|
||||
The two options `GETKEY_REP_PROFILE` and `GETKEY_FEATURES` are only useful when configured through other functions that are not yet available in PythonExtra.
|
||||
|
||||
### Reading keyboard events in real time
|
||||
|
||||
```py
|
||||
pollevent() -> key_event
|
||||
waitevent() -> key_event
|
||||
clearevents() -> None
|
||||
```
|
||||
|
||||
gint records keyboard activity in the background while the program is running. Events are placed in a queue until the program reads them. This is how `getkey()` learns about keyboard activity, for example.
|
||||
|
||||
The `pollevent()` function provides direct access to events. `pollevent()` returns the oldest event that hasn't yet been read by the program. If there are no events waiting to be read, `pollevent()` returns a "fake" event with type `KEYEV_NONE` to indicate that the queue is empty.
|
||||
|
||||
Since `pollevent()` returns instantly, it can be used to read keyboard activity without pausing the program.
|
||||
|
||||
_Example._ A game loop could, at every frame, read all pending events to determine when the player pressed the SHIFT key (in this example the "action" key) to perform an action.
|
||||
|
||||
```py
|
||||
# Render game...
|
||||
|
||||
while True:
|
||||
ev = pollevent()
|
||||
if ev.type == KEYEV_NONE:
|
||||
break # We're done reading events
|
||||
if ev.type == KEYEV_DOWN and ev.key == KEY_SHIFT:
|
||||
pass # The SHIFT key was just pressed!
|
||||
# Implicitly ignores other keys
|
||||
|
||||
# Simulate game...
|
||||
```
|
||||
|
||||
The `waitevent()` function operates similarly, but if there are no pending events it waits for something to happen before returning. It is used quite rarely because in waiting situations one usually uses `getkey()` instead.
|
||||
|
||||
The function `clearevents()` reads and ignores all events, i.e. it "throws away" all the information about recent keyboard activity. It is useful to know the immediate state of the keyboard with `keydown()'` (see below). `clearevents()` is equivalent to the following definition:
|
||||
|
||||
```py
|
||||
def clearevents():
|
||||
ev = pollevent()
|
||||
while ev.type != KEYEV_NONE:
|
||||
ev = pollevent()
|
||||
```
|
||||
|
||||
### Reading the immediate state of the keyboard
|
||||
|
||||
```py
|
||||
keydown(key: int) -> bool
|
||||
keydown_all(*keys: [int]) -> bool
|
||||
keydown_any(*keys: [int]) -> bool
|
||||
```
|
||||
|
||||
After events have been read and the event queue is empty, one can query the immediate state of keys with the `keydown()` function. `keydown(k)` returns `True` if key `k` is currently pressed, `False` otherwise. This function only works **after events have been read**, which is usually done either with `pollevent()` or with `clearevents()`.
|
||||
|
||||
_Example._ A game loop could check the state of the left/right keys at every frame to move the player.
|
||||
|
||||
```py
|
||||
while True:
|
||||
ev = pollevent()
|
||||
# ... same thing as the pollevent() example
|
||||
|
||||
if keydown(KEY_LEFT):
|
||||
player_x -= 1
|
||||
if keydown(KEY_RIGHT):
|
||||
player_x += 1
|
||||
```
|
||||
|
||||
`keydown_all()` takes a series of keys as parameters and returns `True` if they are all pressed. `keydown_any()` is similar and returns `True` if at least one of the listed keys is pressed.
|
||||
|
||||
### Quickly querying key state changes
|
||||
|
||||
```py
|
||||
cleareventflips() -> None
|
||||
keypressed(key: int) -> bool
|
||||
keyreleased(key: int) -> bool
|
||||
```
|
||||
|
||||
`keydown()` only tells whether keys are pressed at a given time; it cannot be used to check when keys change from the released state to the pressed state or the other way around. To do this, one must either read individual events (which can be annoying), remember which keys were pressed at the previous frame, or use the functions described below.
|
||||
|
||||
`keypressed(k)` and `keyreleased(k)` indicate whether key `k` was pressed/released since the last call to `cleareventflips()`. As previously, here "pressed/released" means "as indicated by keyboard events read" not as a real-time state change.
|
||||
|
||||
_Example._ A game loop could test both the immediate state of some keys and state changes for other keys by using immediate functions after `cleareventflips()` followed by `clearevents()`.
|
||||
|
||||
```py
|
||||
# Render game...
|
||||
|
||||
cleareventflips()
|
||||
clearevents()
|
||||
|
||||
if keypressed(KEY_SHIFT):
|
||||
pass # Action !
|
||||
if keydown(KEY_LEFT):
|
||||
player_x -= 1
|
||||
if keydown(KEY_RIGHT):
|
||||
player_x += 1
|
||||
|
||||
# Simulate game...
|
||||
```
|
||||
|
||||
### Miscellaneous keyboard functions
|
||||
|
||||
```py
|
||||
keycode_function(key: int) -> int
|
||||
keycode_digit(key: int) -> int
|
||||
```
|
||||
|
||||
`keycode_function(k)` returns the F-key number of `k` (i.e. 1 for `KEY_F1`, 2 for `KEY_F2`, etc.) and -1 for other keys.
|
||||
|
||||
`keycode_digit(k)` returns the digit associated with `k` (i.e. 0 for `KEY_0`, 1 for `KEY_1`, etc.) and -1 for other keys.
|
||||
|
||||
## Drawing and rendering
|
||||
|
||||
Reference headers: [`<gint/display.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display.h), and for some details [`<gint/display-fx.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-fx.h) and [`<gint/display-cg.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-cg.h).
|
||||
|
||||
### Color manipulation
|
||||
|
||||
```py
|
||||
C_WHITE: int # White
|
||||
C_BLACK: int # Black
|
||||
C_LIGHT: int # Light gray (on B&W: gray engine)
|
||||
C_DARK: int # Dark gray (on B&W: gray engine)
|
||||
C_NONE: int # Transparent
|
||||
C_INVERT: int # Function: inverse
|
||||
|
||||
# Black-and-white (B&W) models only:
|
||||
C_LIGHTEN: int # Function: lighten (gray engine)
|
||||
C_DARKEN: int # Function: darken (gray engine)
|
||||
|
||||
# fx-CG models only:
|
||||
C_RED: int # Pure red
|
||||
C_GREEN: int # Pure green
|
||||
C_BLUE: int # Pure blue
|
||||
C_RGB(r: int, g: int, b: int) -> int
|
||||
```
|
||||
|
||||
Colors are all integers (manipulating `(r,g,b)` tuples is excruciatingly slow and requires memory allocations all over the place). A few default colors are provided.
|
||||
|
||||
On the fx-CG series, the `C_RGB()` function can be used to create colors from three components ranging from 0 to 31.
|
||||
|
||||
TODO: Explain the gray engine.
|
||||
|
||||
### Basic rendering functions
|
||||
|
||||
|
||||
```py
|
||||
DWIDTH: int
|
||||
DHEIGHT: int
|
||||
dupdate() -> None
|
||||
dclear(color: int) -> None
|
||||
dpixel(x: int, y: int, color: int) -> None
|
||||
dgetpixel(x: int, y: int) -> int
|
||||
```
|
||||
|
||||
The integers `DWIDTH` and `DHEIGHT` indicate the screen's dimensions. The screen is 128x64 on black-and-white models (like the G-III) and 396x224 on the fx-CG series (the full screen is available).
|
||||
|
||||
All rendering functions draw to an internal image called the "VRAM"; rendering calls are thus not immediate visible on the screen. For the result to be visible one must call the `dupdate()` function, which transfers the contents of the VRAM to the real display. Usually, this is done after rendering everything we need on one frame instead of after each drawing function call.
|
||||
|
||||
In PythonExtra, `dupdate()` also indicates a "switch to graphics mode". Due to certain optimizations any call to `print()` is considered a "switch to text mode", and while in text mode the shell might redraw at any time. In order to draw after using text mode, one must call `dupdate()` to force a switch to graphics mode before starting rendering. Otherwise the shell and program might render at the same time and produce incoherent results.
|
||||
|
||||
`dclear()` fills the screen with a uniform color.
|
||||
|
||||
`dpixel()` changes a pixel's color. Coordinates, as in every other drawing function, are (x,y) where `x` is in the range 0 to DWIDTH-1 inclusive (0 being left) and `y` is in the range 0 to DHEIGHT-1 inclusive (0 being top).
|
||||
|
||||
`dgetpixel()` returns the color of a pixel. Note that `dgetpixel()` reads from VRAM, not from the display.
|
||||
|
||||
_Example ([`ex_draw1.py`](../../ports/sh/examples/ex_draw1.py))._
|
||||
|
||||
```py
|
||||
from gint import *
|
||||
dclear(C_WHITE)
|
||||
for y in range(10):
|
||||
for x in range(10):
|
||||
if (x^y) & 1:
|
||||
dpixel(x, y, C_BLACK)
|
||||
dupdate()
|
||||
```
|
||||
|
||||
![](images/modgint-draw1-cg.png) ![](images/modgint-draw1-fx.png)
|
||||
|
||||
### Geometric shape rendering functions
|
||||
|
||||
```py
|
||||
drect(x1: int, y1: int, x2: int, y2: int, color: int) -> None
|
||||
drect_border(x1: int, y1: int, x2: int, y2: int, fill_color: int,
|
||||
border_width: int, border_color: int) -> None
|
||||
dline(x1: int, y1: int, x2: int, y2: int, color: int) -> None
|
||||
dhline(y: int, color: int) -> None
|
||||
dvline(x: int, color: int) -> None
|
||||
dcircle(x: int, y: int, radius: int, fill_color: int,
|
||||
border_color: int) -> None
|
||||
dellipse(x1: int, y1: int, x2: int, y2: int, fill_color: int,
|
||||
border_color: int) -> None
|
||||
```
|
||||
|
||||
`drect()` draws a flat rectangle spanning from (x1, y1) to (x2, y2) (both inclusive). The order of points does not matter, i.e. x1 ≥ x2 and y1 ≥ y2 are both allowed.
|
||||
|
||||
`drect_border()` is similar but also draws a border. The border is located _inside_ the rectangle.
|
||||
|
||||
`dline()` draws a straight line from (x1, y1) to (x2, y2). The shortcut functions `dhline()` and `dvline()` draw a full horizontal and vertical line across the screen respectively.
|
||||
|
||||
`dcircle()` draws a circle defined by its center and radius using the Bresenham algorithm. The colors for the circle's interior and its edge can be specified separately, including as `C_NONE` (transparent). By construction, `dcircle()` can only draw circles of odd diameter; for even diameters, use `dellipse()`.
|
||||
|
||||
`dellipse()` draws an ellipse defined by its bounding box. Both (x1, y1) and (x2, y2) are included in the bounding box. To render an ellipse from its center coordinates (x,y) and semi-major/minor axes a/b, use `dellipse(x-a, y-b, x+a, y+b, fill_color, border_color)`.
|
||||
|
||||
_Exemple ([`ex_draw2.py`](../../ports/sh/examples/ex_draw2.py))._
|
||||
|
||||
![](images/modgint-draw2-cg.png) ![](images/modgint-draw2-fx.png)
|
||||
|
||||
_Example ([`ex_circle.py`](../../ports/sh/examples/ex_circle.py))._
|
||||
|
||||
![](images/modgint-circle-cg.png) ![](images/modgint-circle-fx.png)
|
||||
|
||||
### Image rendering functions
|
||||
|
||||
```py
|
||||
dimage(x: int, y: int, img: image) -> None
|
||||
dsubimage(x: int, y: int, img: image, left: int, top: int, width: int, height: int) -> None
|
||||
```
|
||||
|
||||
**On black-and-white models**
|
||||
|
||||
```py
|
||||
image:
|
||||
.profile -> IMAGE_MONO | ...
|
||||
.width -> int
|
||||
.height -> int
|
||||
.data -> buffer-like
|
||||
|
||||
# Constructor
|
||||
image(profile: IMAGE_*, width: int, height: int, data: buffer-like) -> image
|
||||
```
|
||||
|
||||
Images on black-and-white models have either 2 or 4 colors (when the gray engine is enabled). Each image has a `.profile` field indicating the image format (the name "profile" comes from old gint versions), two fields `.width` and `.height` specifying its size, and a `.data` field providing direct access to pixel data.
|
||||
|
||||
The table below lists the four available formats.
|
||||
|
||||
| Format | Colors | Layers | Name in fxconv |
|
||||
|--------------------|---------------------------------|--------|----------------|
|
||||
| `IMAGE_MONO` | Black/white (2) | 1 | `mono` |
|
||||
| `IMAGE_MONO_ALPHA` | Black/white, transparent (3) | 2 | `mono_alpha` |
|
||||
| `IMAGE_GRAY` | Shades of gray (4) | 2 | `gray` |
|
||||
| `IMAGE_GRAY_ALPHA` | Shades of gray, transparent (5) | 3 | `gray_alpha` |
|
||||
|
||||
The raw storage format for data is a bit complicated. The image is stored in row-major order; each line is represented left-to-right by a series of words each covering 32 pixels. Each word contains one bit per pixel (as a 4-byte integer) for each layer.
|
||||
|
||||
The easiest way to obtain an image is to generate the associated code with the fxconv tool from the [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk). The options `--bopti-image-fx --fx` specify a conversion for black-and-white models and the metadata `profile:mono` selects the encoding. The table above lists the value of `profile:` to use for each desired format. For instance for [`fx_image_7seg.py`](../../ports/sh/examples/fx_image_7seg.png) :
|
||||
|
||||
![](../../ports/sh/examples/fx_image_7seg.png)
|
||||
|
||||
```bash
|
||||
% fxconv --bopti-image fx_image_7seg.png -o 7seg.py --fx profile:mono name:seg --py
|
||||
```
|
||||
```py
|
||||
import gint
|
||||
seg = gint.image(0, 79, 12, b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00')
|
||||
```
|
||||
The option `--py-compact` generates much shorter code (less `\x`), however the resulting file can generally not be read or modified by a text editor. The only easy option to use that file is to send it to the calculator and import it as-is. (It can also by manipulated by a program if needed.)
|
||||
|
||||
`dimage()` renders an image, positioned so that the top-left corner of the image is located at (x, y).
|
||||
|
||||
`dsubimage()` renders a sub-rectangle of an image. The rectangle starts at position (left, top) within the image and is of size `width` by `height`. It is positioned so that the (left, top) pixel is drawn at (x, y) on the screen.
|
||||
|
||||
_Example ([`fx_image.py`](../../ports/sh/examples/fx_image.py))._
|
||||
|
||||
![](images/modgint-image-fx.png)
|
||||
|
||||
**On color models**
|
||||
|
||||
```py
|
||||
image:
|
||||
.format -> IMAGE_RGB565 | ...
|
||||
.flags -> int
|
||||
.color_count -> int
|
||||
.width -> int
|
||||
.height -> int
|
||||
.stride -> int
|
||||
.data -> buffer-like
|
||||
.palette -> buffer-like
|
||||
|
||||
# Constructor
|
||||
image(format: IMAGE_*, color_count: int, width: int, height: int, stride: int, data: buffer-like, palette: buffer-like) -> image
|
||||
|
||||
# Format-specific constructors
|
||||
image_rgb565(width: int, height: int, data: buffer-like) -> image
|
||||
image_rgb565a(width: int, height: int, data: buffer-like) -> image
|
||||
image_p8_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p8_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p4_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p4_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
```
|
||||
|
||||
Images on color models are available in multiple formats as indicated by the `.format` field; the possible values are listed below. Formats differ in the number of colors, the presence of a transparent color, and the presence of a palette. Of course, the less colors the smaller the memory footprint of the image, so in general it is very beneficial to use the smallest format in which an image fits.
|
||||
|
||||
| Format | Colors | Palette | Name in fxconv |
|
||||
|--------------------|---------------------|-------------|----------------|
|
||||
| `IMAGE_RGB565` | 65536 | No | `rgb565` |
|
||||
| `IMAGE_RGB565A` | 65535 + transparent | No | `rgb565a` |
|
||||
| `IMAGE_P8_RGB565` | 256 | Yes (1-256) | `p8_rgb565` |
|
||||
| `IMAGE_P8_RGB565A` | 255 + transparent | Yes (1-256) | `p8_rgb565a` |
|
||||
| `IMAGE_P4_RGB565` | 16 | Yes (16) | `p4_rgb565` |
|
||||
| `IMAGE_P4_RGB565A` | 15 + transparent | Yes (16) | `p4_rgb565a` |
|
||||
|
||||
The `.color_count` field indicates the number of colors in the palette, when there is one. For P8 formats this number varies between 1 and 256, and for P4 formats it is always equal to 16. The `.width` and `.height` fields indicate the image's size. Finally, the `.data` and `.palette` fields provide direct access to the raw data for the image's pixels and color palette.
|
||||
|
||||
(The `.flags` field has details of memory management that shouldn't be important to Python scripts. The `.stride` fields indicates the distance in bytes between rows of pixels in `.data` and should similarly be of rare use.)
|
||||
|
||||
The functions `dimage()` and `dsubimage()` work the same way as for black-and-white models; please see above.
|
||||
|
||||
As for black-and-white models, images can be converted into a Python format with fxconv. For instance with [`cg_image_puzzle.png`](../../ports/sh/examples/cg_image_puzzle.png) (full encoding elided):
|
||||
|
||||
![](../../ports/sh/examples/cg_image_puzzle.png)
|
||||
|
||||
```bash
|
||||
% fxconv --bopti-image cg_image_puzzle.png -o puzzle.py --cg profile:p4_rgb565 name:puzzle --py
|
||||
```
|
||||
```py
|
||||
import gint
|
||||
puzzle = gint.image(6, 16, 64, 32, 32,
|
||||
b'\xbb\xbb\xbb\xbb\xbb ... \xdd\xdd\xdd\xdd\xdd\xdd\xdd',
|
||||
b'\xff\xff\xcfW\x86\xd8\xbe|\xceP\xe5\x8a\x963f9u\x9c}\xa8\x9dxD\xfa\x83\xceLNZ\xcci\xa7')
|
||||
```
|
||||
The option `--py-compact` is recommended to reduce code size; please see details in the black-and-white section above.
|
||||
|
||||
_Exemple ([`cg_image.py`](../../ports/sh/examples/cg_image.py))._
|
||||
|
||||
![](images/modgint-image-cg.png)
|
||||
|
||||
## Differences with gint's C API
|
||||
|
||||
- `dsubimage()` doesn't have its final parameter `int flags`. The flags are only minor optimizations and could be removed in future gint versions.
|
||||
- Image constructors`image()` and `image_<format>()` don't exist in the C API.
|
||||
- Asynchronous volatile-flag-based timeouts are replaced with synchronous millisecond delays (integer value or `None`).
|
||||
|
||||
TODO: There are more.
|
|
@ -0,0 +1,434 @@
|
|||
# `gint`: Module d'accès aux fonctionnalités de gint
|
||||
|
||||
PythonExtra est écrit à l'aide du [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) et utilise [gint](https://gitea.planet-casio.com/Lephenixnoir/gint) pour exécuter l'add-in. Le module Python `gint` permet d'accéder aux fonctions internes de gint en Python pour le dessin, le clavier, etc. Comme gint possède beaucoup de fonctions utiles avec de bonnes performances, il est intéressant de s'en servir au lieu d'utiliser e.g. `casioplot` ou `turtle`.
|
||||
|
||||
Le module `gint` essaie de garder en Python la même API que dans la version originale de la bibliothèque en C, c'est pourquoi peu de fonctions utilisent des arguments nommés ou autres fonctions surchargées. Il y a quelques différences, documentées à la fin de cette page. En cas de doute, la documentation fournie par les [fichiers d'en-tête de gint](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint) (les `.h`) est tout à fait applicable pour comprendre les comportements que cette page n'explique pas.
|
||||
|
||||
Tous les noms de constantes, fonctions, etc. discutés dans cet article sont dans le module `gint`.
|
||||
|
||||
```py
|
||||
import gint
|
||||
# ou:
|
||||
from gint import *
|
||||
```
|
||||
|
||||
**Sommaire**
|
||||
- [Saisie au clavier](#saisie-au-clavier)
|
||||
- [Dessin à l'écran](#dessin-à-lécran)
|
||||
- [Différences avec l'API C de gint](#différences-avec-lapi-c-de-gint)
|
||||
|
||||
## Saisie au clavier
|
||||
|
||||
Les en-têtes de référence sont [`<gint/keyboard.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keyboard.h) et [`<gint/keycodes.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keycodes.h).
|
||||
|
||||
### Noms des touches
|
||||
|
||||
Le module fournit des constantes entières désignant toutes les touches du clavier. Les noms sont les suivants :
|
||||
|
||||
| | | | | | |
|
||||
|------------|------------|------------|------------|------------|-------------|
|
||||
|`KEY_F1` |`KEY_F2` |`KEY_F3` |`KEY_F4` |`KEY_F5` |`KEY_F6` |
|
||||
|`KEY_SHIFT` |`KEY_OPTN` |`KEY_VARS` |`KEY_MENU` |`KEY_LEFT` |`KEY_UP` |
|
||||
|`KEY_ALPHA` |`KEY_SQUARE`|`KEY_POWER` |`KEY_EXIT` |`KEY_DOWN` |`KEY_RIGHT` |
|
||||
|`KEY_XOT` |`KEY_LOG` |`KEY_LN` |`KEY_SIN` |`KEY_COS` |`KEY_TAN` |
|
||||
|`KEY_FRAC` |`KEY_FD` |`KEY_LEFTP` |`KEY_RIGHTP`|`KEY_COMMA` |`KEY_ARROW` |
|
||||
|`KEY_7` |`KEY_8` |`KEY_9` |`KEY_DEL` |`KEY_ACON` | |
|
||||
|`KEY_4` |`KEY_5` |`KEY_6` |`KEY_MUL` |`KEY_DIV` | |
|
||||
|`KEY_1` |`KEY_2` |`KEY_3` |`KEY_ADD` |`KEY_SUB` | |
|
||||
|`KEY_0` |`KEY_DOT` |`KEY_EXP` |`KEY_NEG` |`KEY_EXE` | |
|
||||
|
||||
### Événements clavier
|
||||
|
||||
```
|
||||
key_event:
|
||||
.time -> int
|
||||
.mod -> bool
|
||||
.shift -> bool
|
||||
.alpha -> bool
|
||||
.type -> KEYEV_NONE | KEYEV_DOWN | KEYEV_UP | KEYEV_HOLD
|
||||
.key -> KEY_*
|
||||
```
|
||||
|
||||
gint communique les informations sur ce qu'il se passe au clavier via des _événements_. Les événements indiquent quand une touche (champ `.key`) a été pressée, maintenue, ou relâchée (champ `.type` égal à `KEYEV_DOWN`, `KEYEV_HOLD` et `KEYEV_UP` respectivement), quand (champ `.time`) et si des modifieurs (SHIFT ou ALPHA, champs `.shift` et `.alpha`) étaient actifs à ce moment-là.
|
||||
|
||||
(Le champ `.mod` n'est pas très intéressant, et la valeur `KEYEV_NONE` de `.type` est discutée dans `pollevent()`.)
|
||||
|
||||
Les fonctions `getkey()`, `getekey_opt()`, `pollevent()` et `waitevent()` renvoient toutes des événements.
|
||||
|
||||
### Saisie d'une touche avec attente
|
||||
|
||||
```py
|
||||
getkey() -> key_event
|
||||
getkey_opt(opts: GETKEY_*, timeout_ms: int | None) -> key_event
|
||||
```
|
||||
|
||||
La fonction `getkey()` met le programme en pause jusqu'à ce qu'une touche soit pressée ou répétée, et renvoie l'événement associé (qui est forcément de type `KEYEV_DOWN` ou `KEYEV_HOLD`). Par défaut, les seules touches qui sont répétées sont les touches directionnelles, une première fois après 400 ms, et ensuite toutes les 40 ms.
|
||||
|
||||
Pas mal de choses peuvent se produire pendant l'exécution de `getkey()`. L'utilisateur peut appuyer sur SHIFT ou ALPHA, ce qui affecte les champs `.shift` et `.alpha` de l'événement renvoyé. L'utilisateur peut également se rendre au menu principal avec MENU et éteindre la calculatrice avec SHIFT+AC/ON.
|
||||
|
||||
_Exemple._ Dans un menu de sélection de N éléments, on pourrait naviguer avec les touches haut et bas, sauter directement au début ou à la fin avec SHIFT haut et SHIFT bas, et valider avec EXE.
|
||||
|
||||
```py
|
||||
ev = getkey()
|
||||
if ev.key == KEY_EXE:
|
||||
pass # Valider
|
||||
elif ev.key == KEY_UP and ev.shift:
|
||||
pos = 0 # Revenir au début
|
||||
elif ev.key == KEY_DOWN and ev.shift:
|
||||
pos = N-1 # Aller à la fin
|
||||
elif ev.key == KEY_UP and pos > 0:
|
||||
pos -= 1 # Monter d'une position
|
||||
elif ev.key == KEY_DOWN and pos < N-1:
|
||||
pos += 1 # Descendre d'une position
|
||||
```
|
||||
|
||||
La fonction `getkey_opt()` est une généralisation de `getkey()` qui donne accès à plus d'options pour personnaliser le comportement de la fonction. Le paramètre `opts` accepte une combinaison d'options dans le tableau ci-dessous, et le paramètre `timeout_ms`, quand il n'est pas `None`, spécifie au bout de combien de temps la fonction doit s'arrêter et renvoyer un événement de type `KEYEV_NONE` s'il n'y a aucune activité sur le clavier. Le délai est exprimé en millisecondes mais la précision réelle est de l'ordre de 7-8 ms.
|
||||
|
||||
| Option | `getkey()` | Description |
|
||||
|------------------------|------------|------------------------------------------------------------|
|
||||
| `GETKEY_MOD_SHIFT` | Oui | La touche SHIFT est un modifieur |
|
||||
| `GETKEY_MOD_ALPHA` | Oui | La touche ALPHA est un modifieur |
|
||||
| `GETKEY_BACKLIGHT` | Oui | SHIFT+OPTN allume/éteint le rétroéclairage |
|
||||
| `GETKEY_MENU` | Oui | MENU retourne au menu principal de la calculatrice |
|
||||
| `GETKEY_REP_ARROWS` | Oui | Répète les touches directionnelles si maintenues |
|
||||
| `GETKEY_REP_ALL` | Non | Répète toutes les touches si maintenues |
|
||||
| `GETKEY_REP_PROFILE` | Oui* | Personnalisation des durées de répétition |
|
||||
| `GETKEY_FEATURES` | Oui* | Personnalisation des raccourcis claviers globaux |
|
||||
| `GETKEY_MENU_DUPDATE` | Oui | Rafraîchit l'écran après un retour au menu (Prizm/G90) |
|
||||
| `GETKEY_MENU_EVENT` | Non | Envoie un événement `KEYEV_OSMENU` après un retour au menu |
|
||||
| `GETKEY_POWEROFF` | Oui | SHIFT+AC/ON éteint la calculatrice |
|
||||
|
||||
`getkey()` est équivalent à `getkey_opt(opts, None)` où `opts` est la somme de toutes les options marquées "Oui" dans la colonne `getkey()` ci-dessus.
|
||||
|
||||
Les deux options `GETKEY_REP_PROFILE` et `GETKEY_FEATURES` ne sont utiles qu'au travers de fonctions de configuration qui ne sont pour l'instant pas disponibles dans PythonExtra.
|
||||
|
||||
### Lecture des événements en temps réel
|
||||
|
||||
```py
|
||||
pollevent() -> key_event
|
||||
waitevent() -> key_event
|
||||
clearevents() -> None
|
||||
```
|
||||
|
||||
gint enregistre l'activité du clavier en tâche de fond pendant que le programme s'exécute. Les événements sont mis dans une file d'attente jusqu'à ce que le programme les lise. C'est comme ça par exemple que `getkey()` détermine quoi renvoyer.
|
||||
|
||||
Il est possible d'accéder aux événements directement à l'aide de la fonction `pollevent()`. `pollevent()` renvoie l'événement le plus ancien qui n'a pas encore été lu par le programme. Si le programme a lu tous les événements et qu'il n'y a plus rien en attente, `pollevent()` renvoie un "faux" évenement de type `KEYEV_NONE` pour indiquer qu'il n'y a plus rien à lire.
|
||||
|
||||
Comme `pollevent()` retourne instanténement, on peut s'en servir pour lire l'activité du clavier sans mettre le programme en pause.
|
||||
|
||||
_Exemple._ Une boucle de jeu pourrait, à chaque frame, lire tous les événements en attente pour déterminer quand le joueur appuie sur la touche SHIFT ("action" dans cet exemple) pour déclencher une action.
|
||||
|
||||
```py
|
||||
# Dessiner le jeu...
|
||||
|
||||
while True:
|
||||
ev = pollevent()
|
||||
if ev.type == KEYEV_NONE:
|
||||
break # Fin de la lecture des événements
|
||||
if ev.type == KEYEV_DOWN and ev.key == KEY_SHIFT:
|
||||
pass # La touche SHIFT vient d'être pressée !
|
||||
# Ignore implicitement les autres touches
|
||||
|
||||
# Simuler le jeu...
|
||||
```
|
||||
|
||||
La fonction `waitevent()` est similaire, mais si tous les événements ont été lus elle attend qu'un événement se produise avant de retourner. Elle est plus rarement utilisée parce qu'en général quand on veut attendre on utilise `getkey()`.
|
||||
|
||||
La fonction `clearevents()` lit et ignore tous les événements, i.e. elle "jette" toutes les informations sur ce qu'il s'est passé au clavier. Elle est utile pour connaître l'état instantané du clavier avec `keydown()` (voir ci-dessous). `clearevents()` est équivalente à la définition suivante :
|
||||
|
||||
```py
|
||||
def clearevents():
|
||||
ev = pollevent()
|
||||
while ev.type != KEYEV_NONE:
|
||||
ev = pollevent()
|
||||
```
|
||||
|
||||
### Lecture de l'état instantané du clavier
|
||||
|
||||
```py
|
||||
keydown(key: int) -> bool
|
||||
keydown_all(*keys: [int]) -> bool
|
||||
keydown_any(*keys: [int]) -> bool
|
||||
```
|
||||
|
||||
Une fois les événements lus, on peut tester individuellement si les touches sont pressées ou pas à l'aide de la fonction `keydown()`. `keydown(k)` renvoie `True` si la touche `k` est pressée, `False` sinon. Cette fonction ne marche **que si les événements ont été lus**, ce qu'on fait souvent soit avec `pollevent()` soit avec `clearevents()`.
|
||||
|
||||
_Exemple._ Une boucle de jeu pourrait tester si les touches gauche/droite sont pressées à chaque frame pour déplacer le joueur.
|
||||
|
||||
```py
|
||||
while True:
|
||||
ev = pollevent()
|
||||
# ... comme dans l'exemple pollevent()
|
||||
|
||||
if keydown(KEY_LEFT):
|
||||
player_x -= 1
|
||||
if keydown(KEY_RIGHT):
|
||||
player_x += 1
|
||||
```
|
||||
|
||||
La fonction `keydown_all()` prent une série de touches en paramètre et renvoie `True` si elles sout toutes pressées. `keydown_any()` est similaire et renvoie `True` si au moins une des touches listées est pressée.
|
||||
|
||||
### Lecture rapide des changements de position des touches
|
||||
|
||||
```py
|
||||
cleareventflips() -> None
|
||||
keypressed(key: int) -> bool
|
||||
keyreleased(key: int) -> bool
|
||||
```
|
||||
|
||||
`keydown()` indique uniquement l'état instantané des touches. Elle ne permet pas de déterminer à quel moment une touche passe de l'état relâché à l'état pressé ou l'inverse. Pour ça, il faut soit utiliser les événements (ce qui est un peu lourd), soit se souvenir de quelles touches étaient pressées à "l'instant" précédent, soit utiliser les fonctions ci-dessous.
|
||||
|
||||
Les fonctions `keypressed(k)` et `keyreleased(k)` indiquent si la touche a été pressée/relâchée depuis le dernier appel à `cleareventflips()`. Attention la notion de "pressée/relâchée" ici n'est pas le temps réel mais la lecture des événements.
|
||||
|
||||
_Exemple._ Une boucle de jeu peut tester à la fois l'état immédiat et les changements d'état des touches en utilisant les fonctions instantanée après `cleareventflips()` suivi de `clearevents()`.
|
||||
|
||||
```py
|
||||
# Dessiner le jeu...
|
||||
|
||||
cleareventflips()
|
||||
clearevents()
|
||||
|
||||
if keypressed(KEY_SHIFT):
|
||||
pass # Action !
|
||||
if keydown(KEY_LEFT):
|
||||
player_x -= 1
|
||||
if keydown(KEY_RIGHT):
|
||||
player_x += 1
|
||||
|
||||
# Simuler le jeu...
|
||||
```
|
||||
|
||||
### Fonctions diverses concernant le clavier
|
||||
|
||||
```py
|
||||
keycode_function(key: int) -> int
|
||||
keycode_digit(key: int) -> int
|
||||
```
|
||||
|
||||
`keycode_function(k)` renvoie le numéro de F-touche de `k` (i.e. 1 pour `KEY_F1`, 2 pour `KEY_F2`, etc.) et -1 pour les autres touches.
|
||||
|
||||
`keycode_digit(k)` renvoie le chiffre associé à `k` (i.e. 0 pour `KEY_0`, 1 pour `KEY_1`, etc.) et -1 pour les autres touches.
|
||||
|
||||
## Dessin à l'écran
|
||||
|
||||
Les en-têtes de référence sont [`<gint/display.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display.h), et pour certains détails techniques [`<gint/display-fx.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-fx.h) et [`<gint/display-cg.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-cg.h).
|
||||
|
||||
### Manipulation de couleurs
|
||||
|
||||
```py
|
||||
C_WHITE: int # Blanc
|
||||
C_BLACK: int # Noir
|
||||
C_LIGHT: int # Gris clair (sur mono: moteur de gris)
|
||||
C_DARK: int # Gris foncé (sur mono: moteur de gris)
|
||||
C_NONE: int # Transparent
|
||||
C_INVERT: int # Inverseur de couleur
|
||||
|
||||
# Graph mono uniquement :
|
||||
C_LIGHTEN: int # Éclaircisseur de couleur (moteur de gris)
|
||||
C_DARKEN: int # Assombrisseur de couleur (moteur de gris)
|
||||
|
||||
# Graph 90+E uniquement :
|
||||
C_RED: int # Rouge pur
|
||||
C_GREEN: int # Vert pur
|
||||
C_BLUE: int # Bleu pur
|
||||
C_RGB(r: int, g: int, b: int) -> int
|
||||
```
|
||||
|
||||
Les couleurs sont toutes des nombres entiers (manipuler des tuples `(r,g,b)` est atrocement lent par comparaison et requiert des allocations mémoire dans tous les sens). Une poignée de couleurs est fournie par défaut.
|
||||
|
||||
Sur Graph 90+E, la fonction `C_RGB()` peut être utilisée pour créer des couleurs à partir de trois composantes de valeur 0 à 31.
|
||||
|
||||
TODO: Expliquer le moteur de gris.
|
||||
|
||||
### Fonctions de dessin basiques
|
||||
|
||||
```py
|
||||
DWIDTH: int
|
||||
DHEIGHT: int
|
||||
dupdate() -> None
|
||||
dclear(color: int) -> None
|
||||
dpixel(x: int, y: int, color: int) -> None
|
||||
dgetpixel(x: int, y: int) -> int
|
||||
```
|
||||
|
||||
Les entiers `DWIDTH` et `DHEIGHT` indiquent la taille de l'écran. C'est 128x64 sur les Graph mono (type Graph 35+E II), 396x224 sur la Prizm et Graph 90+E (le plein écran est disponible).
|
||||
|
||||
Toutes les fonctions de dessin opèrent sur une image interne appellée "VRAM" ; l'effet du dessin n'est donc pas visible immédiatement à l'écran. Pour que le dessin se voie il faut appeler la fonction `dupdate()` qui transfère les contenus de la VRAM à l'écran réel. Généralement, on fait ça après avoir affiché tout ce dont on a besoin et pas après chaque appel de fonction de dessin.
|
||||
|
||||
Dans PythonExtra, la fonction `dupdate()` indique aussi implicitement qu'on « passe en mode graphique ». À cause de certaines optimisations tout appel à `print()` est considéré comme un « passage en mode texte » et pendant qu'on est en mode texte le shell peut redessiner à tout moment. Si on veut dessiner après avoir utilisé le mode texte, il faut appeler `dupdate()` pour forcer un passage en mode graphique avant de commencer à dessiner. Sinon le dessin du shell pourrait interférer avec le dessin du programme.
|
||||
|
||||
La fonction `dclear()` remplit l'écran d'une couleur unie.
|
||||
|
||||
La fonction `dpixel()` modifie la couleur d'un pixel. Les coordonnées, comme pour toutes les fonctions de dessin, sont (x,y) où `x` varie entre 0 et DWIDTH-1 inclus (0 étant à gauche), et `y` varie entre 0 et DHEIGHT-1 inclus (0 étant en haut).
|
||||
|
||||
La fonction `dgetpixel()` renvoie la couleur d'un pixel. Attention, `dgetpixel()` lit dans la VRAM, pas sur l'écran.
|
||||
|
||||
_Exemple ([`ex_draw1.py`](../../ports/sh/examples/ex_draw1.py))._
|
||||
|
||||
```py
|
||||
from gint import *
|
||||
dclear(C_WHITE)
|
||||
for y in range(10):
|
||||
for x in range(10):
|
||||
if (x^y) & 1:
|
||||
dpixel(x, y, C_BLACK)
|
||||
dupdate()
|
||||
```
|
||||
|
||||
![](images/modgint-draw1-cg.png) ![](images/modgint-draw1-fx.png)
|
||||
|
||||
### Fonctions de dessin de formes géométriques
|
||||
|
||||
```py
|
||||
drect(x1: int, y1: int, x2: int, y2: int, color: int) -> None
|
||||
drect_border(x1: int, y1: int, x2: int, y2: int, fill_color: int,
|
||||
border_width: int, border_color: int) -> None
|
||||
dline(x1: int, y1: int, x2: int, y2: int, color: int) -> None
|
||||
dhline(y: int, color: int) -> None
|
||||
dvline(x: int, color: int) -> None
|
||||
dcircle(x: int, y: int, radius: int, fill_color: int,
|
||||
border_color: int) -> None
|
||||
dellipse(x1: int, y1: int, x2: int, y2: int, fill_color: int,
|
||||
border_color: int) -> None
|
||||
```
|
||||
|
||||
`drect()` dessine un rectangle plein allant de (x1, y1) à (x2, y2) (tous les deux inclus). L'ordre des points ne compte pas, i.e. x1 ≥ x2 ou y1 ≥ y2 est autorisé.
|
||||
|
||||
`drect_border()` est similaire mais dessine une bordure de largeur `border_width` et de couleur `border_color`. La bordure est dessinée _à l'intérieur_ du rectangle.
|
||||
|
||||
`dline()` dessine une ligne droite entre les points (x1, y1) et (x2, y2). Les raccourcis `dhline()` et `dvline()` dessinent respectivement une ligne horizontale et verticale à travers tout l'écran.
|
||||
|
||||
`dcircle()` dessine un cercle défini par son centre et rayon avec l'algorithme de Bresenham. La couleur de l'intérieur et du bord peuvent être spécifiées séparément, y compris avec `C_NONE` (transparente). Par construction, `dcircle()` ne peut construire que des cercles de diamètre impair ; pour les diamètres plus fin, utilisez `dellipse()`.
|
||||
|
||||
`dellipse()` dessine une ellipse définie par son rectangle englobant. Les points (x1, y1) et (x2, y2) sont tous les deux inclus dans le rectangle. Pour dessiner une ellipse à partir de son centre (x, y) et de ses demi-grand/petit axes a/b, utilisez `dellipse(x-a, y-b, x+a, y+b, fill_color, border_color)`.
|
||||
|
||||
_Exemple ([`ex_draw2.py`](../../ports/sh/examples/ex_draw2.py))._
|
||||
|
||||
![](images/modgint-draw2-cg.png) ![](images/modgint-draw2-fx.png)
|
||||
|
||||
_Exemple ([`ex_circle.py`](../../ports/sh/examples/ex_circle.py))._
|
||||
|
||||
![](images/modgint-circle-cg.png) ![](images/modgint-circle-fx.png)
|
||||
|
||||
### Fonctions de dessin d'images
|
||||
|
||||
```py
|
||||
dimage(x: int, y: int, img: image) -> None
|
||||
dsubimage(x: int, y: int, img: image, left: int, top: int, width: int, height: int) -> None
|
||||
```
|
||||
|
||||
**Sur Graph mono**
|
||||
|
||||
```py
|
||||
image:
|
||||
.profile -> IMAGE_MONO | ...
|
||||
.width -> int
|
||||
.height -> int
|
||||
.data -> buffer-like
|
||||
|
||||
# Constructeur
|
||||
image(profile: IMAGE_*, width: int, height: int, data: buffer-like) -> image
|
||||
```
|
||||
|
||||
Les images sur Graph mono sont en noir-et-blanc ou 4 couleurs (quand le moteur de gris est utilisé). Chaque image a un champ `.profile` indiquant le format d'image (le nom "profile" est hérité d'anciennes versions de gint), deux champs `.width` et `.height` indiquant sa taille, et un champ `.data` donnant accès aux données brutes.
|
||||
|
||||
Les quatre formats disponibles sont les suivants.
|
||||
|
||||
| Format | Couleurs | Calques | Nom dans fxconv |
|
||||
|--------------------|----------------------------------|---------|-----------------|
|
||||
| `IMAGE_MONO` | Noir/blanc (2) | 1 | `mono` |
|
||||
| `IMAGE_MONO_ALPHA` | Noir/blanc, transparent (3) | 2 | `mono_alpha` |
|
||||
| `IMAGE_GRAY` | Niveaux de gris (4) | 2 | `gray` |
|
||||
| `IMAGE_GRAY_ALPHA` | Niveaux de gris, transparent (5) | 3 | `gray_alpha` |
|
||||
|
||||
Le format des données brutes est un peu compliqué. L'image est stockée ligne par ligne de haut en bas ; chaque ligne est représentée de gauche à droite par une série de mots représentant chacun 32 pixels. Chaque mot contient un bit par pixel (sous la forme d'un entier de 4 octets) pour chaque calque.
|
||||
|
||||
Le plus simple pour obtenir une image est de générer le code associé avec l'outil fxconv du [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk). Les options `--bopti-image-fx --fx` spécifient qu'on convertit une image pour Graph mono et la métadonnée `profile:mono` choisit le format de l'image produite. Le tableau ci-dessus liste la valeur de `profile:` à spécifier pour chaque format. Par exemple pour l'image [`fx_image_7seg.py`](../../ports/sh/examples/fx_image_7seg.png) :
|
||||
|
||||
![](../../ports/sh/examples/fx_image_7seg.png)
|
||||
|
||||
```bash
|
||||
% fxconv --bopti-image fx_image_7seg.png -o 7seg.py --fx profile:mono name:seg --py
|
||||
```
|
||||
```py
|
||||
import gint
|
||||
seg = gint.image(0, 79, 12, b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00')
|
||||
```
|
||||
L'option `--py-compact` permet de générer du code beaucoup plus compact (avec moins de `\x`), par contre le fichier obtenu ne peut pas être lu par un éditeur de texte. La seule option simple pour l'utiliser est de l'envoyer sur la calculatrice et l'importer tel quel (on peut aussi le manipuler avec un programme).
|
||||
|
||||
La fonction `dimage()` dessine une image à l'écran en positionnant le coin haut gauche de l'image à la position (x, y).
|
||||
|
||||
La fonction `dsubimage()` permet de dessiner un sous-rectangle d'une image. Le sous-rectangle commence à la position (left, top) de l'image et s'étend sur une largeur `width` et une hauteur `height`. Le sous-rectangle est dessiné de façon à ce que le pixel (left, top) arrive à la position (x, y) de l'écran.
|
||||
|
||||
_Exemple ([`fx_image.py`](../../ports/sh/examples/fx_image.py))._
|
||||
|
||||
![](images/modgint-image-fx.png)
|
||||
|
||||
**Sur Graph couleur**
|
||||
|
||||
```py
|
||||
image:
|
||||
.format -> IMAGE_RGB565 | ...
|
||||
.flags -> int
|
||||
.color_count -> int
|
||||
.width -> int
|
||||
.height -> int
|
||||
.stride -> int
|
||||
.data -> buffer-like
|
||||
.palette -> buffer-like
|
||||
|
||||
# Constructeur
|
||||
image(format: IMAGE_*, color_count: int, width: int, height: int, stride: int, data: buffer-like, palette: buffer-like) -> image
|
||||
|
||||
# Constructeurs spécialisés par format
|
||||
image_rgb565(width: int, height: int, data: buffer-like) -> image
|
||||
image_rgb565a(width: int, height: int, data: buffer-like) -> image
|
||||
image_p8_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p8_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p4_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
image_p4_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
|
||||
```
|
||||
|
||||
Les images sur Graph couleur sont déclinées en différents formats indiqués par le champ `.format`, dont les valeurs possibles sont listées ci-dessous. Les différences sont dans le nombre de couleurs, la présence ou pas de transparence, et la présence ou pas d'une palette de couleurs. Bien sûr, moins il y a de couleurs moins l'image prend de place en mémoire, donc de façon générale il est très bénéfique d'utiliser le plus petit format possible pour chaque image.
|
||||
|
||||
| Format | Couleurs | Palette | Nom dans fxconv |
|
||||
|--------------------|---------------------|-------------|-----------------|
|
||||
| `IMAGE_RGB565` | 65536 | Non | `rgb565` |
|
||||
| `IMAGE_RGB565A` | 65535 + transparent | Non | `rgb565a` |
|
||||
| `IMAGE_P8_RGB565` | 256 | Oui (1-256) | `p8_rgb565` |
|
||||
| `IMAGE_P8_RGB565A` | 255 + transparent | Oui (1-256) | `p8_rgb565a` |
|
||||
| `IMAGE_P4_RGB565` | 16 | Oui (16) | `p4_rgb565` |
|
||||
| `IMAGE_P4_RGB565A` | 15 + transparent | Oui (16) | `p4_rgb565a` |
|
||||
|
||||
Le champ `.color_count` indique le nombre de couleurs dans la palette quand il y en a une. Pour les formats P8 ce nombre varie entre 1 et 256, pour les formats P4 il est toujours égal à 16. Les deux champs `.width` et `.height` indiquent la taille de l'image. Enfin, les champs `.data` et `.palette` permettent d'accéder aux données brutes des pixels ainsi que de la palette.
|
||||
|
||||
(Le champ `.flags` est un détail de gestion de mémoire qui ne devrait pas importer aux scripts Python. Le champ `.stride` indique combien d'octets séparent chaque ligne de pixels dans `.data` et sera de même rarement utilisé.)
|
||||
|
||||
Les fonctions `dimage()` et `dsubimage()` ont le même fonctionnement que pour les Graph mono ; voir ci-dessus.
|
||||
|
||||
Comme pour Graph mono les images peuvent être converties avec fxconv. Par exemple pour l'image [`cg_image_puzzle.png`](../../ports/sh/examples/cg_image_puzzle.png) (code abrégé) :
|
||||
|
||||
![](../../ports/sh/examples/cg_image_puzzle.png)
|
||||
|
||||
```bash
|
||||
% fxconv --bopti-image cg_image_puzzle.png -o puzzle.py --cg profile:p4_rgb565 name:puzzle --py
|
||||
```
|
||||
```py
|
||||
import gint
|
||||
puzzle = gint.image(6, 16, 64, 32, 32,
|
||||
b'\xbb\xbb\xbb\xbb\xbb ... \xdd\xdd\xdd\xdd\xdd\xdd\xdd',
|
||||
b'\xff\xff\xcfW\x86\xd8\xbe|\xceP\xe5\x8a\x963f9u\x9c}\xa8\x9dxD\xfa\x83\xceLNZ\xcci\xa7')
|
||||
```
|
||||
L'option `--py-compact` est recommandée pour réduire la taille du code ; voir les détails dans la section Graph mono.
|
||||
|
||||
_Exemple ([`cg_image.py`](../../ports/sh/examples/cg_image.py))._
|
||||
|
||||
![](images/modgint-image-cg.png)
|
||||
|
||||
## Différences avec l'API C de gint
|
||||
|
||||
- `dsubimage()` n'a pas de paramètre `int flags`. Les flags en question ne ont que des optimisations mineures et pourraient disparaître dans une version future de gint.
|
||||
- Les constructeurs d'image `image()` et `image_<format>()` n'existent pas dans l'API C.
|
||||
- Les timeouts asynchrones à base d'entiers volatiles sont remplacés par des timeouts synchrones avec des durées optionnelles en millisecondes (entier ou `None`).
|
||||
|
||||
TODO : Il y en a d'autres.
|
|
@ -0,0 +1,2 @@
|
|||
/PythonExtra.g1a
|
||||
/PythonEx.g1a
|
|
@ -0,0 +1,24 @@
|
|||
include ../../py/mkenv.mk
|
||||
|
||||
SH_CFLAGS := -DFX9860G
|
||||
TARGETCASIO := "FX9860G"
|
||||
SH_LDFLAGS := -T fx9860g.ld -ljustui-fx -lm -lgint-fx -lc -lgint-fx -lgcc
|
||||
|
||||
SH_ASSETS := \
|
||||
img_fkeys_main.png img_modifier_states.png \
|
||||
font_5x7.png font_4x4.png font_4x6.png font_3x5.png
|
||||
SH_METADATA := fxconv-metadata.txt
|
||||
SH_CONVFLAGS := --fx
|
||||
|
||||
all: PythonEx.g1a
|
||||
|
||||
ICON_RELEASE := icon.png
|
||||
ICON_DEV := icon-dev.png
|
||||
|
||||
PythonEx.g1a: $(BUILD)/firmware.bin icon.png icon-dev.png
|
||||
fxgxa --g1a -n PythonExtra -i $(ICON_$(BUILDTYPE)) $< -o $@
|
||||
|
||||
send: all
|
||||
fxlink -sw PythonEx.g1a
|
||||
|
||||
include $(TOP)/ports/sh/Makefile
|
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 809 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,37 @@
|
|||
img_*.png:
|
||||
type: bopti-image
|
||||
name_regex: (.*)\.png \1
|
||||
|
||||
font_*.png:
|
||||
name_regex: (.*)\.png \1
|
||||
type: font
|
||||
charset: print
|
||||
grid.padding: 1
|
||||
grid.border: 0
|
||||
|
||||
font_5x7.png:
|
||||
charset: print
|
||||
grid.size: 5x7
|
||||
grid.padding: 1
|
||||
grid.border: 0
|
||||
|
||||
font_4x4.png:
|
||||
charset: print
|
||||
grid.size: 4x4
|
||||
grid.padding: 1
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
|
||||
font_4x6.png:
|
||||
charset: print
|
||||
grid.size: 5x6
|
||||
grid.padding: 1
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
|
||||
font_3x5.png:
|
||||
charset: ascii
|
||||
height: 5
|
||||
grid.size: 5x6
|
||||
grid.padding: 1
|
||||
proportional: true
|
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 7.9 KiB |
|
@ -0,0 +1 @@
|
|||
../sh/mpconfigport.h
|
|
@ -0,0 +1 @@
|
|||
/*.g3a
|
|
@ -0,0 +1,22 @@
|
|||
include ../../py/mkenv.mk
|
||||
|
||||
SH_CFLAGS := -DFXCG50
|
||||
TARGETCASIO := "FXCG50"
|
||||
SH_LDFLAGS := -T fxcg50.ld -ljustui-cg -lm -lgint-cg -lc -lgint-cg -lgcc
|
||||
|
||||
SH_ASSETS := img_modifier_states.png font_9.png font_13.png font_19.png PoliceNW
|
||||
SH_METADATA := fxconv-metadata.txt
|
||||
SH_CONVFLAGS := --cg
|
||||
|
||||
all: PythonExtra.g3a
|
||||
|
||||
ICONS_RELEASE := --icon-uns=icon-uns.png --icon-sel=icon-sel.png
|
||||
ICONS_DEV := --icon-uns=icon-uns-dev.png --icon-sel=icon-sel-dev.png
|
||||
|
||||
PythonExtra.g3a: $(BUILD)/firmware.bin
|
||||
fxgxa --g3a -n PythonExtra $(ICONS_$(BUILDTYPE)) $< -o $@
|
||||
|
||||
send: all
|
||||
fxlink -sw PythonExtra.g3a
|
||||
|
||||
include $(TOP)/ports/sh/Makefile
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,40 @@
|
|||
img_*.png:
|
||||
type: bopti-image
|
||||
name_regex: (.*)\.png \1
|
||||
profile: p4
|
||||
|
||||
font_9.png:
|
||||
name: font_9
|
||||
type: font
|
||||
charset: print
|
||||
grid.size: 9x10
|
||||
grid.padding: 0
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
|
||||
font_13.png:
|
||||
name: font_13
|
||||
type: font
|
||||
charset: print
|
||||
grid.size: 12x17
|
||||
grid.padding: 0
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
|
||||
font_19.png:
|
||||
name: font_19
|
||||
type: font
|
||||
charset: print
|
||||
grid.size: 18x23
|
||||
grid.padding: 0
|
||||
grid.border: 0
|
||||
proportional: true
|
||||
|
||||
PoliceNW:
|
||||
name: numworks
|
||||
type: font
|
||||
charset: unicode
|
||||
grid.size: 10x16
|
||||
grid.padding: 0
|
||||
grid.border: 0
|
||||
proportional: true
|
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 802 B |
|
@ -0,0 +1 @@
|
|||
../sh/mpconfigport.h
|
|
@ -29,6 +29,7 @@
|
|||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/modbluetooth.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#include "extmod/mpbthci.h"
|
||||
#include "shared/runtime/softtimer.h"
|
||||
#include "modmachine.h"
|
||||
|
|
|
@ -41,9 +41,6 @@
|
|||
|
||||
// For regular code that wants to prevent "background tasks" from running.
|
||||
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
|
||||
// TODO: Check for the settings of the STM32 port in irq.h
|
||||
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003)
|
||||
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
|
||||
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
|
||||
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
|
||||
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
|
||||
|
|
|
@ -129,6 +129,7 @@ set(MICROPY_SOURCE_PORT
|
|||
mphalport.c
|
||||
mpnetworkport.c
|
||||
mpthreadport.c
|
||||
mutex_extra.c
|
||||
pendsv.c
|
||||
rp2_flash.c
|
||||
rp2_pio.c
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "py/mpthread.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "mutex_extra.h"
|
||||
|
||||
#if MICROPY_PY_THREAD
|
||||
|
||||
|
@ -45,27 +46,23 @@ STATIC uint32_t *core1_stack = NULL;
|
|||
STATIC size_t core1_stack_num_words = 0;
|
||||
|
||||
// Thread mutex.
|
||||
STATIC mp_thread_mutex_t atomic_mutex;
|
||||
STATIC mutex_t atomic_mutex;
|
||||
|
||||
uint32_t mp_thread_begin_atomic_section(void) {
|
||||
if (core1_entry) {
|
||||
// When both cores are executing, we also need to provide
|
||||
// full mutual exclusion.
|
||||
mp_thread_mutex_lock(&atomic_mutex, 1);
|
||||
// In case this atomic section is for flash access, then
|
||||
// suspend the other core.
|
||||
multicore_lockout_start_blocking();
|
||||
return mutex_enter_blocking_and_disable_interrupts(&atomic_mutex);
|
||||
} else {
|
||||
return save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
return save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
void mp_thread_end_atomic_section(uint32_t state) {
|
||||
restore_interrupts(state);
|
||||
|
||||
if (core1_entry) {
|
||||
multicore_lockout_end_blocking();
|
||||
mp_thread_mutex_unlock(&atomic_mutex);
|
||||
if (atomic_mutex.owner != LOCK_INVALID_OWNER_ID) {
|
||||
mutex_exit_and_restore_interrupts(&atomic_mutex, state);
|
||||
} else {
|
||||
restore_interrupts(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +70,7 @@ void mp_thread_end_atomic_section(uint32_t state) {
|
|||
void mp_thread_init(void) {
|
||||
assert(get_core_num() == 0);
|
||||
|
||||
mp_thread_mutex_init(&atomic_mutex);
|
||||
mutex_init(&atomic_mutex);
|
||||
|
||||
// Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core1.
|
||||
multicore_lockout_victim_init();
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "mutex_extra.h"
|
||||
|
||||
// These functions are taken from lib/pico-sdk/src/common/pico_sync/mutex.c and modified
|
||||
// so that they atomically obtain the mutex and disable interrupts.
|
||||
|
||||
uint32_t __time_critical_func(mutex_enter_blocking_and_disable_interrupts)(mutex_t * mtx) {
|
||||
lock_owner_id_t caller = lock_get_caller_owner_id();
|
||||
do {
|
||||
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
||||
if (!lock_is_owner_id_valid(mtx->owner)) {
|
||||
mtx->owner = caller;
|
||||
spin_unlock_unsafe(mtx->core.spin_lock);
|
||||
return save;
|
||||
}
|
||||
lock_internal_spin_unlock_with_wait(&mtx->core, save);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void __time_critical_func(mutex_exit_and_restore_interrupts)(mutex_t * mtx, uint32_t save) {
|
||||
spin_lock_unsafe_blocking(mtx->core.spin_lock);
|
||||
assert(lock_is_owner_id_valid(mtx->owner));
|
||||
mtx->owner = LOCK_INVALID_OWNER_ID;
|
||||
lock_internal_spin_unlock_with_notify(&mtx->core, save);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_RP2_MUTEX_EXTRA_H
|
||||
#define MICROPY_INCLUDED_RP2_MUTEX_EXTRA_H
|
||||
|
||||
#include "pico/mutex.h"
|
||||
|
||||
uint32_t mutex_enter_blocking_and_disable_interrupts(mutex_t *mtx);
|
||||
void mutex_exit_and_restore_interrupts(mutex_t *mtx, uint32_t save);
|
||||
|
||||
#endif // MICROPY_INCLUDED_RP2_MUTEX_EXTRA_H
|
|
@ -70,6 +70,22 @@ bi_decl(bi_block_device(
|
|||
BINARY_INFO_BLOCK_DEV_FLAG_WRITE |
|
||||
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN));
|
||||
|
||||
// Flash erase and write must run with interrupts disabled and the other core suspended,
|
||||
// because the XIP bit gets disabled.
|
||||
static uint32_t begin_critical_flash_section(void) {
|
||||
if (multicore_lockout_victim_is_initialized(1 - get_core_num())) {
|
||||
multicore_lockout_start_blocking();
|
||||
}
|
||||
return save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
static void end_critical_flash_section(uint32_t state) {
|
||||
restore_interrupts(state);
|
||||
if (multicore_lockout_victim_is_initialized(1 - get_core_num())) {
|
||||
multicore_lockout_end_blocking();
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// Parse arguments
|
||||
enum { ARG_start, ARG_len };
|
||||
|
@ -135,19 +151,17 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
|
|||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||
if (n_args == 3) {
|
||||
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
|
||||
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||
mp_uint_t atomic_state = begin_critical_flash_section();
|
||||
flash_range_erase(self->flash_base + offset, bufinfo.len);
|
||||
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
||||
end_critical_flash_section(atomic_state);
|
||||
mp_event_handle_nowait();
|
||||
// TODO check return value
|
||||
} else {
|
||||
offset += mp_obj_get_int(args[3]);
|
||||
}
|
||||
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
|
||||
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||
mp_uint_t atomic_state = begin_critical_flash_section();
|
||||
flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len);
|
||||
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
||||
end_critical_flash_section(atomic_state);
|
||||
mp_event_handle_nowait();
|
||||
// TODO check return value
|
||||
return mp_const_none;
|
||||
|
@ -170,10 +184,9 @@ STATIC mp_obj_t rp2_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_
|
|||
return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES);
|
||||
case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: {
|
||||
uint32_t offset = mp_obj_get_int(arg_in) * BLOCK_SIZE_BYTES;
|
||||
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
|
||||
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||
mp_uint_t atomic_state = begin_critical_flash_section();
|
||||
flash_range_erase(self->flash_base + offset, BLOCK_SIZE_BYTES);
|
||||
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
||||
end_critical_flash_section(atomic_state);
|
||||
// TODO check return value
|
||||
return MP_OBJ_NEW_SMALL_INT(0);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,8 @@ CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU) -fsingle
|
|||
CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__
|
||||
CFLAGS += $(CFLAGS_EXTRA)
|
||||
|
||||
CFLAGS += -DMICROPY_HW_CODESIZE=$(MICROPY_HW_CODESIZE)
|
||||
# Strip the letter 'K' from MICROPY_HW_CODESIZE for use by C code.
|
||||
CFLAGS += -DMICROPY_HW_CODESIZE=$(strip $(subst K,' ', $(MICROPY_HW_CODESIZE)))
|
||||
|
||||
LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref
|
||||
LDFLAGS += --defsym=_codesize=$(MICROPY_HW_CODESIZE)
|
||||
|
|
|
@ -33,13 +33,5 @@
|
|||
extern uint32_t time_offset;
|
||||
|
||||
MP_WEAK DWORD get_fattime(void) {
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
return (RTC->MODE2.CLOCK.reg >> 1) + (20 << 25);
|
||||
#else
|
||||
extern void rtc_gettime(timeutils_struct_time_t *tm);
|
||||
timeutils_struct_time_t tm;
|
||||
timeutils_seconds_since_epoch_to_struct_time(mp_hal_ticks_ms_64() / 1000 + time_offset, &tm);
|
||||
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) |
|
||||
((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec / 2);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include "extmod/modmachine.h"
|
||||
#include "sam.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
|
||||
typedef struct _machine_rtc_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t callback;
|
||||
|
@ -177,5 +175,3 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
|||
make_new, machine_rtc_make_new,
|
||||
locals_dict, &machine_rtc_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_RTC
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
include("$(PORT_DIR)/boards/manifest.py")
|
||||
include("$(MPY_DIR)/extmod/asyncio")
|
||||
require("onewire")
|
||||
require("ds18x20")
|
||||
require("dht")
|
|
@ -1,25 +1,28 @@
|
|||
// Deinitions common to all SAMD21 boards
|
||||
#include "samd21.h"
|
||||
|
||||
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES)
|
||||
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES)
|
||||
#if MICROPY_HW_CODESIZE == 248
|
||||
#define SAMD21_EXTRA_FEATURES 1
|
||||
#else
|
||||
#define SAMD21_EXTRA_FEATURES 0
|
||||
#endif
|
||||
|
||||
// MicroPython emitters
|
||||
#define MICROPY_EMIT_THUMB (0)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
#define MICROPY_EMIT_THUMB (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_EMIT_THUMB_ARMV7M (0)
|
||||
#define MICROPY_MODULE_BUILTIN_INIT (1)
|
||||
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
|
||||
#ifndef MICROPY_PY_BUILTINS_COMPLEX
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_TIME
|
||||
#define MICROPY_PY_TIME (1)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_MATH
|
||||
#define MICROPY_PY_MATH (1)
|
||||
#define MP_NEED_LOG2 (1)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_BUILTINS_COMPLEX
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_CMATH
|
||||
|
@ -29,13 +32,36 @@
|
|||
#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (trng_random_u32(300))
|
||||
unsigned long trng_random_u32(int delay);
|
||||
|
||||
#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
|
||||
|
||||
#ifndef MICROPY_HW_UART_TXBUF
|
||||
#define MICROPY_HW_UART_TXBUF (1)
|
||||
#endif
|
||||
#ifndef MICROPY_HW_UART_RTSCTS
|
||||
#define MICROPY_HW_UART_RTSCTS (SAMD21_EXTRA_FEATURES)
|
||||
#endif
|
||||
|
||||
// selected extensions of the extra features set
|
||||
#define MICROPY_PY_OS_URANDOM (1)
|
||||
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_COMP_RETURN_IF_EXPR (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_OPT_MPZ_BITWISE (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_BUILTINS_STR_CENTER (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_BUILTINS_STR_PARTITION (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_BUILTINS_ROUND_INT (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_SYS_STDIO_BUFFER (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_FRAMEBUF (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_ASYNCIO (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_SELECT (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_ERRNO (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_DEFLATE (SAMD21_EXTRA_FEATURES)
|
||||
#define MICROPY_PY_ONEWIRE (SAMD21_EXTRA_FEATURES)
|
||||
|
||||
#ifndef MICROPY_PY_MACHINE_PIN_BOARD_CPU
|
||||
#define MICROPY_PY_MACHINE_PIN_BOARD_CPU (1)
|
||||
#endif
|
||||
|
||||
#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
|
||||
|
||||
#define CPU_FREQ (48000000)
|
||||
#define DFLL48M_FREQ (48000000)
|
||||
|
|
|
@ -6,6 +6,10 @@ MPY_CROSS_MCU_ARCH = armv6m
|
|||
|
||||
MICROPY_HW_CODESIZE ?= 184K
|
||||
|
||||
ifeq ($(MICROPY_HW_CODESIZE), 248K)
|
||||
FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py
|
||||
endif
|
||||
|
||||
MICROPY_VFS_LFS1 ?= 1
|
||||
|
||||
SRC_S += shared/runtime/gchelper_thumb1.s
|
||||
|
|
|
@ -42,7 +42,7 @@ PA16,0,,10,30,20,06
|
|||
PA17,1,,11,31,21,07
|
||||
PA18,2,,12,32,30,02
|
||||
PA19,3,,13,33,31,03
|
||||
PB16,9,,50,,60,04
|
||||
PB16,0,,50,,60,04
|
||||
PB17,1,,51,,61,05
|
||||
PA20,4,,52,32,70,04
|
||||
PA21,5,,53,33,71,07
|
||||
|
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#define MICROPY_PY_OS_SYNC (1)
|
||||
#define MICROPY_PY_OS_URANDOM (1)
|
||||
#define MICROPY_PY_ONEWIRE (1)
|
||||
#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (trng_random_u32())
|
||||
unsigned long trng_random_u32(void);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# Rows not starting with pa, pb, pc or pd are ignored.
|
||||
# When editing the table with a spread sheet, take care to import the data as text.
|
||||
Pin,EIC,ADC0,ADC1,SERCOM1,SERCOM2,TC,TCC1,TCC2
|
||||
PB03,9,15,,,51,61,,
|
||||
PB03,3,15,,,51,61,,
|
||||
PA00,0,,,,10,20,,
|
||||
PA01,1,,,,11,21,,
|
||||
PC00,0,,10,,,,,
|
||||
|
@ -87,7 +87,7 @@ PA22,6,,,30,51,40,16,02
|
|||
PA23,7,,,31,50,41,17,03
|
||||
PA24,8,,,32,52,50,22,
|
||||
PA25,9,,,33,53,51,,
|
||||
PB22,22,,,12,52,70,,
|
||||
PB22,6,,,12,52,70,,
|
||||
PB23,7,,,13,53,71,,
|
||||
PB24,8,,,00,21,,,
|
||||
PB25,9,,,01,20,,,
|
||||
|
@ -107,6 +107,6 @@ PB30,14,,,70,51,00,40,06
|
|||
PB31,15,,,71,50,01,41,07
|
||||
PC30,14,,12,,,,,
|
||||
PC31,15,,13,,,,,
|
||||
PB00,9,12,,,52,70,,
|
||||
PB00,0,12,,,52,70,,
|
||||
PB01,1,13,,,53,71,,
|
||||
PB02,2,14,,,50,60,22,
|
||||
|
|
|
|
@ -48,16 +48,10 @@
|
|||
|
||||
#define LIGHTSLEEP_CPU_FREQ 200000
|
||||
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
#define MICROPY_PY_MACHINE_RTC_ENTRY { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
|
||||
#else
|
||||
#define MICROPY_PY_MACHINE_RTC_ENTRY
|
||||
#endif
|
||||
|
||||
#define MICROPY_PY_MACHINE_EXTRA_GLOBALS \
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, \
|
||||
MICROPY_PY_MACHINE_RTC_ENTRY \
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, \
|
||||
\
|
||||
/* Class constants. */ \
|
||||
/* Use numerical constants instead of the symbolic names, */ \
|
||||
|
|
|
@ -107,9 +107,6 @@
|
|||
#define MICROPY_PY_UCTYPES (1)
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
#define MICROPY_PY_RANDOM (1)
|
||||
#define MICROPY_PY_DEFLATE (1)
|
||||
#define MICROPY_PY_ASYNCIO (1)
|
||||
#define MICROPY_PY_MACHINE_RTC (1)
|
||||
#ifndef MICROPY_PY_MACHINE_ADC
|
||||
#define MICROPY_PY_MACHINE_ADC (1)
|
||||
#endif
|
||||
|
@ -151,7 +148,6 @@
|
|||
#define MICROPY_PY_MACHINE_WDT (1)
|
||||
#define MICROPY_PY_MACHINE_WDT_INCLUDEFILE "ports/samd/machine_wdt.c"
|
||||
#define MICROPY_PY_MACHINE_WDT_TIMEOUT_MS (1)
|
||||
#define MICROPY_PY_ONEWIRE (1)
|
||||
#define MICROPY_PY_PLATFORM (1)
|
||||
#define MICROPY_PLATFORM_VERSION "ASF4"
|
||||
|
||||
|
|
|
@ -38,9 +38,7 @@
|
|||
#include "tusb.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
extern void machine_rtc_start(bool force);
|
||||
#endif
|
||||
|
||||
static void usb_init(void) {
|
||||
// Init USB clock
|
||||
|
@ -124,9 +122,7 @@ void samd_init(void) {
|
|||
#if defined(MCU_SAMD51)
|
||||
mp_hal_ticks_cpu_enable();
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
machine_rtc_start(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
/exclude/
|
||||
/PythonExtra*.zip
|
||||
/numworks/ion_backup.c
|
|
@ -0,0 +1,93 @@
|
|||
CROSS_COMPILE := sh-elf-
|
||||
|
||||
include $(TOP)/py/py.mk
|
||||
include $(TOP)/extmod/extmod.mk
|
||||
|
||||
CFLAGS += -m4-nofpu -mb -fstrict-volatile-bitfields \
|
||||
-I. -I$(TOP)/ports/sh -I$(BUILD) -I$(TOP) \
|
||||
$(SH_CFLAGS) -Os -Wall -Wextra -Wno-unused-parameter
|
||||
LIBS += -nostdlib -Wl,--no-warn-rwx-segments $(SH_LDFLAGS) -Wl,-Map=build/map
|
||||
|
||||
# Source files
|
||||
SRC_C = \
|
||||
ports/sh/main.c \
|
||||
ports/sh/console.c \
|
||||
ports/sh/debug.c \
|
||||
ports/sh/keymap.c \
|
||||
ports/sh/modcasioplot.c \
|
||||
ports/sh/modgint.c \
|
||||
ports/sh/mphalport.c \
|
||||
ports/sh/objgintimage.c \
|
||||
ports/sh/pyexec.c \
|
||||
ports/sh/resources.c \
|
||||
ports/sh/stredit.c \
|
||||
ports/sh/widget_shell.c \
|
||||
shared/runtime/gchelper_generic.c \
|
||||
shared/runtime/stdout_helpers.c \
|
||||
shared/runtime/interrupt_char.c \
|
||||
|
||||
SRC_QSTR += \
|
||||
ports/sh/main.c \
|
||||
ports/sh/modcasioplot.c \
|
||||
ports/sh/modgint.c \
|
||||
ports/sh/objgintimage.c \
|
||||
ports/sh/pyexec.c \
|
||||
|
||||
|
||||
ifeq ($(TARGETCASIO),"FXCG50")
|
||||
$(info ************ FXCG50 VERSION ************ )
|
||||
$(info ********* Add Numworks modules ********* )
|
||||
SRC_C += \
|
||||
ports/sh/numworks/modkandinsky.c \
|
||||
ports/sh/numworks/modion.c \
|
||||
|
||||
SRC_QSTR += \
|
||||
ports/sh/numworks/modkandinsky.c \
|
||||
ports/sh/numworks/modion.c \
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETCASIO),"FX9860G")
|
||||
$(info *********** FX9860G VERSION *********** )
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(shell [[ x"$$(git describe)" == x"$$(git describe main)" ]] \
|
||||
&& [[ -z "$$(git status -uno --porcelain)" ]] \
|
||||
&& echo y),y)
|
||||
$(info * RELEASE BUILD)
|
||||
BUILDTYPE := RELEASE
|
||||
else
|
||||
$(info * DEVELOPMENT BUILD)
|
||||
BUILDTYPE := DEV
|
||||
endif
|
||||
|
||||
ASSETS_O := $(SH_ASSETS:%=$(BUILD)/sh_assets/%.o)
|
||||
|
||||
OBJ = $(PY_O) $(ASSETS_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
|
||||
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
|
||||
$(Q)$(CC:gcc=objcopy) -O binary -R .bss -R .gint_bss $< $@
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
$(BUILD)/sh_assets/%.o: % $(SH_METADATA)
|
||||
$(Q)mkdir -p $(dir $@)
|
||||
$(Q)fxconv --toolchain=$(CROSS_COMPILE:%-=%) $(SH_CONVFLAGS) $< -o $@
|
||||
|
||||
ARCHIVE := PythonExtra-$(shell git describe).zip
|
||||
|
||||
# Weird rules calling back to fxcg50 and fx9860g3, both of whic include this
|
||||
release:
|
||||
$(MAKE) -C ../fx9860g3
|
||||
$(MAKE) -C ../fxcg50
|
||||
cd ../sh && zip "$(ARCHIVE)" -j ../fx9860g3/PythonEx.g1a ../fxcg50/PythonExtra.g3a
|
||||
cd ../sh && zip "$(ARCHIVE)" -r examples modules
|
||||
|
||||
.PHONY: release
|
||||
.PRECIOUS: $(ARCHIVE)
|
||||
|
||||
include $(TOP)/py/mkrules.mk
|
|
@ -0,0 +1,552 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// ____ PythonExtra //
|
||||
//.-'`_ o `;__, A community port of MicroPython for CASIO calculators. //
|
||||
//.-'` `---` ' License: MIT (except some files; see LICENSE) //
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/kmalloc.h>
|
||||
#include <gint/defs/util.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "console.h"
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "../../shared/readline/readline.h"
|
||||
#include "keymap.h"
|
||||
|
||||
/* Compute the shell's horizontal layout as:
|
||||
1. Text width (region where the text is rendered)
|
||||
2. Spacing left of the scrollbar
|
||||
3. Width of the scrollbar */
|
||||
static void view_params(int w,
|
||||
int *text_w, int *scroll_spacing, int *scroll_width)
|
||||
{
|
||||
#ifdef FX9860G
|
||||
if(text_w)
|
||||
*text_w = w - 2;
|
||||
if(scroll_spacing)
|
||||
*scroll_spacing = 1;
|
||||
if(scroll_width)
|
||||
*scroll_width = 1;
|
||||
#else
|
||||
if(text_w)
|
||||
*text_w = w - 4;
|
||||
if(scroll_spacing)
|
||||
*scroll_spacing = 2;
|
||||
if(scroll_width)
|
||||
*scroll_width = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=== Static console lines ===//
|
||||
|
||||
void console_fline_update_render_lines(console_fline_t *FL, int width)
|
||||
{
|
||||
char const *p = FL->data;
|
||||
FL->render_lines = 0;
|
||||
|
||||
do {
|
||||
FL->render_lines++;
|
||||
p = drsize(p, NULL, width, NULL);
|
||||
}
|
||||
while(*p);
|
||||
}
|
||||
|
||||
int console_fline_render(int x, int y, console_fline_t *FL, int w, int dy,
|
||||
int show_from, int show_until, int cursor)
|
||||
{
|
||||
char const *p = FL->data;
|
||||
char const *endline = p + FL->size;
|
||||
int line_offset = 0;
|
||||
int line_number = 0;
|
||||
|
||||
if(p == endline && cursor == 0) {
|
||||
int h;
|
||||
dsize("", NULL, NULL, &h);
|
||||
dline(x, y, x, y+h-1, C_BLACK);
|
||||
}
|
||||
while(p < endline) {
|
||||
char const *endscreen = drsize(p, NULL, w, NULL);
|
||||
int len = endscreen - p;
|
||||
|
||||
if(line_number >= show_from && line_number < show_until) {
|
||||
dtext_opt(x, y, C_BLACK, C_NONE, DTEXT_LEFT, DTEXT_TOP, p, len);
|
||||
if(cursor >= line_offset && cursor <= line_offset + len) {
|
||||
int w, h;
|
||||
dnsize(p, cursor - line_offset, NULL, &w, &h);
|
||||
dline(x+w, y, x+w, y+h-1, C_BLACK);
|
||||
}
|
||||
y += dy;
|
||||
}
|
||||
|
||||
p += len;
|
||||
line_offset += len;
|
||||
line_number++;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
//=== Rotating line storage ===//
|
||||
|
||||
bool linebuf_init(linebuf_t *buf, int capacity, int backlog_size)
|
||||
{
|
||||
if(capacity <= 0)
|
||||
return false;
|
||||
|
||||
buf->lines = kmalloc(capacity * sizeof *buf->lines, PE_CONSOLE_LINE_ALLOC);
|
||||
if(!buf->lines)
|
||||
return false;
|
||||
memset(buf->lines, 0, capacity * sizeof *buf->lines);
|
||||
|
||||
stredit_init(&buf->edit, 0, 0, 0);
|
||||
|
||||
buf->capacity = capacity;
|
||||
buf->start = 0;
|
||||
buf->size = 0;
|
||||
buf->absolute = 1;
|
||||
buf->backlog_size = backlog_size;
|
||||
buf->total_size_except_last = 0;
|
||||
buf->absolute_rendered = 0;
|
||||
buf->total_rendered = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void linebuf_deinit(linebuf_t *buf)
|
||||
{
|
||||
stredit_reset(&buf->edit);
|
||||
for(int i = 0; i < buf->capacity; i++)
|
||||
free(buf->lines[i]);
|
||||
kfree((void *)buf->lines);
|
||||
memset(buf, 0, sizeof *buf);
|
||||
}
|
||||
|
||||
/* Lines in the buffer are identified by their positions within the `lines`
|
||||
array, which are integers equipped with modulo arithmetic (we call them
|
||||
"indices"). We abstract away the rotation by numbering stored lines from 0
|
||||
to buf->size - 1, and we call these numbers "nths". When we want to identify
|
||||
lines independent of rotation, we use their absolute line number.
|
||||
|
||||
Such numbers refer to lines stored in the buffer if:
|
||||
(index) 0 <= index < size
|
||||
(nth) 0 <= nth < size
|
||||
(abs) 0 <= abs - buf->absolute < size */
|
||||
|
||||
GINLINE static int linebuf_nth_to_index(linebuf_t const *buf, int nth)
|
||||
{
|
||||
return (buf->start + nth) % buf->capacity;
|
||||
}
|
||||
|
||||
/* Get the nth line. */
|
||||
GINLINE static console_fline_t *linebuf_get_nth_line(linebuf_t const *buf,
|
||||
int nth)
|
||||
{
|
||||
if(nth < 0 || nth >= buf->size)
|
||||
return NULL;
|
||||
|
||||
if(nth == buf->size - 1)
|
||||
return (console_fline_t *)buf->edit.raw;
|
||||
else
|
||||
return buf->lines[linebuf_nth_to_index(buf, nth)];
|
||||
}
|
||||
|
||||
/* Move `index` by `diff`; assumes |diff| <= buf->capacity. */
|
||||
GINLINE static int linebuf_index_add(linebuf_t const *buf, int index, int diff)
|
||||
{
|
||||
return (index + diff + buf->capacity) % buf->capacity;
|
||||
}
|
||||
|
||||
int linebuf_start(linebuf_t const *buf)
|
||||
{
|
||||
return buf->absolute;
|
||||
}
|
||||
|
||||
int linebuf_end(linebuf_t const *buf)
|
||||
{
|
||||
return buf->absolute + buf->size;
|
||||
}
|
||||
|
||||
console_fline_t *linebuf_get_line(linebuf_t const *buf, int abs)
|
||||
{
|
||||
return linebuf_get_nth_line(buf, abs - buf->absolute);
|
||||
}
|
||||
|
||||
stredit_t *linebuf_get_last_line(linebuf_t *buf)
|
||||
{
|
||||
return (buf->size > 0) ? &buf->edit : NULL;
|
||||
}
|
||||
|
||||
stredit_t *linebuf_newline(linebuf_t *buf)
|
||||
{
|
||||
/* Make space if the buffer is full */
|
||||
linebuf_recycle_oldest_lines(buf, buf->size - buf->capacity + 1);
|
||||
|
||||
/* Freeze the current last line and reset the editor */
|
||||
if(buf->size > 0) {
|
||||
buf->total_size_except_last += buf->edit.size;
|
||||
|
||||
int size = buf->edit.size;
|
||||
console_fline_t *frozen = (void *)stredit_freeze_and_reset(&buf->edit);
|
||||
frozen->size = size;
|
||||
|
||||
int last_nth = linebuf_nth_to_index(buf, buf->size - 1);
|
||||
assert(buf->lines[last_nth] == NULL);
|
||||
buf->lines[last_nth] = frozen;
|
||||
}
|
||||
|
||||
buf->size++;
|
||||
int last_nth = linebuf_nth_to_index(buf, buf->size - 1);
|
||||
buf->lines[last_nth] = NULL;
|
||||
stredit_init(&buf->edit, 16, CONSOLE_FLINE_SIZE,
|
||||
PE_CONSOLE_LINE_MAX_LENGTH);
|
||||
return &buf->edit;
|
||||
}
|
||||
|
||||
void linebuf_recycle_oldest_lines(linebuf_t *buf, int count)
|
||||
{
|
||||
count = min(count, buf->size);
|
||||
if(count <= 0)
|
||||
return;
|
||||
|
||||
for(int nth = 0; nth < count; nth++) {
|
||||
console_fline_t *FL = linebuf_get_nth_line(buf, nth);
|
||||
buf->total_rendered -= FL->render_lines;
|
||||
if(nth != buf->size - 1)
|
||||
buf->total_size_except_last -= FL->size;
|
||||
free(FL);
|
||||
}
|
||||
|
||||
buf->start = linebuf_index_add(buf, buf->start, count);
|
||||
buf->size -= count;
|
||||
buf->absolute += count;
|
||||
}
|
||||
|
||||
void linebuf_clean_backlog(linebuf_t *buf)
|
||||
{
|
||||
if(buf->size <= 0)
|
||||
return;
|
||||
|
||||
int remove = 0;
|
||||
int n = buf->total_size_except_last + linebuf_get_last_line(buf)->size;
|
||||
|
||||
while(remove < buf->size - 1 && n > buf->backlog_size) {
|
||||
n -= linebuf_get_nth_line(buf, remove)->size;
|
||||
remove++;
|
||||
}
|
||||
|
||||
linebuf_recycle_oldest_lines(buf, remove);
|
||||
}
|
||||
|
||||
void linebuf_update_render(linebuf_t *buf, int width, bool lazy)
|
||||
{
|
||||
int start = linebuf_start(buf);
|
||||
int end = linebuf_end(buf);
|
||||
if(lazy)
|
||||
start = max(start, buf->absolute_rendered + 1);
|
||||
|
||||
int text_w;
|
||||
view_params(width, &text_w, NULL, NULL);
|
||||
|
||||
for(int abs = start; abs < end; abs++) {
|
||||
console_fline_t *FL = linebuf_get_nth_line(buf, abs - buf->absolute);
|
||||
buf->total_rendered -= FL->render_lines;
|
||||
console_fline_update_render_lines(FL, text_w);
|
||||
buf->total_rendered += FL->render_lines;
|
||||
}
|
||||
|
||||
buf->absolute_rendered = max(buf->absolute_rendered, end - 2);
|
||||
}
|
||||
|
||||
//=== Terminal emulator ===//
|
||||
|
||||
console_t *console_create(int backlog_size, int maximum_line_count)
|
||||
{
|
||||
backlog_size = max(backlog_size, PE_CONSOLE_LINE_MAX_LENGTH);
|
||||
maximum_line_count = max(maximum_line_count, 1);
|
||||
|
||||
console_t *cons = malloc(sizeof *cons);
|
||||
if(!linebuf_init(&cons->lines, maximum_line_count, backlog_size)) {
|
||||
free(cons);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cons->cursor = -1;
|
||||
cons->render_needed = true;
|
||||
cons->render_font = NULL;
|
||||
cons->render_width = 0;
|
||||
cons->render_lines = 0;
|
||||
|
||||
console_newline(cons);
|
||||
return cons;
|
||||
}
|
||||
|
||||
void console_newline(console_t *cons)
|
||||
{
|
||||
linebuf_newline(&cons->lines);
|
||||
cons->cursor = 0;
|
||||
cons->render_needed = true;
|
||||
|
||||
/* This is a good time to clean up the backlog. */
|
||||
// TODO: This might actually be the performance bottleneck, because we do a
|
||||
// long loop only to find out that the total size is still reasonable!
|
||||
linebuf_clean_backlog(&cons->lines);
|
||||
}
|
||||
|
||||
void console_clear_render_flag(console_t *cons)
|
||||
{
|
||||
cons->render_needed = false;
|
||||
}
|
||||
|
||||
void console_destroy(console_t *cons)
|
||||
{
|
||||
linebuf_deinit(&cons->lines);
|
||||
free(cons);
|
||||
}
|
||||
|
||||
//=== Rendering functions ===//
|
||||
|
||||
void console_compute_view(console_t *cons, font_t const *font,
|
||||
int width, int lines)
|
||||
{
|
||||
/* If a view with the same width was previously computed, do a lazy
|
||||
update: recompute only the last lines. */
|
||||
bool lazy = (width != 0 && cons->render_width == width);
|
||||
cons->render_font = font;
|
||||
cons->render_width = width;
|
||||
cons->render_lines = lines;
|
||||
|
||||
font_t const *old_font = dfont(font);
|
||||
linebuf_update_render(&cons->lines, width, lazy);
|
||||
dfont(old_font);
|
||||
}
|
||||
|
||||
console_scrollpos_t console_clamp_scrollpos(console_t const *cons,
|
||||
console_scrollpos_t pos)
|
||||
{
|
||||
/* No scrolling case */
|
||||
if(cons->lines.total_rendered < cons->render_lines)
|
||||
return 0;
|
||||
|
||||
return max(0, min(pos, cons->lines.total_rendered - cons->render_lines));
|
||||
}
|
||||
|
||||
void console_render(int x, int y0, console_t *cons, int dy,
|
||||
console_scrollpos_t pos)
|
||||
{
|
||||
int total_lines = cons->lines.total_rendered;
|
||||
int visible_lines = cons->render_lines;
|
||||
int w = cons->render_width;
|
||||
int y = y0;
|
||||
|
||||
int text_w, scroll_spacing, scroll_w;
|
||||
view_params(w, &text_w, &scroll_spacing, &scroll_w);
|
||||
|
||||
font_t const *old_font = dfont(cons->render_font);
|
||||
|
||||
/* Normally only frozen lines have a valid size field. Update the size of
|
||||
the last line so we don't have to make an exception for it. */
|
||||
stredit_t *ed = linebuf_get_last_line(&cons->lines);
|
||||
console_fline_t *ed_FL = (console_fline_t *)ed->raw;
|
||||
ed_FL->size = ed->size;
|
||||
|
||||
/* Show only visible lines. We want to avoid counting all the lines in the
|
||||
console, and instead start from the end. */
|
||||
int line_y = visible_lines + pos;
|
||||
int L_start = linebuf_start(&cons->lines);
|
||||
int L_end = linebuf_end(&cons->lines);
|
||||
int i = linebuf_end(&cons->lines);
|
||||
|
||||
while(i > L_start && line_y > 0)
|
||||
line_y -= linebuf_get_line(&cons->lines, --i)->render_lines;
|
||||
|
||||
/* If there isn't enough content to fill the view, start at the top. */
|
||||
line_y = min(line_y, pos);
|
||||
|
||||
while(i < L_end && line_y < visible_lines) {
|
||||
console_fline_t *FL = linebuf_get_line(&cons->lines, i);
|
||||
bool show_cursor = (i == L_end - 1);
|
||||
|
||||
y = console_fline_render(x, y, FL, text_w, dy, -line_y,
|
||||
visible_lines - line_y, show_cursor ? cons->cursor : -1);
|
||||
line_y += FL->render_lines;
|
||||
i++;
|
||||
}
|
||||
|
||||
dfont(old_font);
|
||||
|
||||
/* Scrollbar */
|
||||
if(total_lines > visible_lines) {
|
||||
int first_shown = total_lines - visible_lines - pos;
|
||||
int h = dy * visible_lines;
|
||||
int y1 = y0 + h * first_shown / total_lines;
|
||||
int y2 = y0 + h * (first_shown + visible_lines) / total_lines;
|
||||
|
||||
int color = C_BLACK;
|
||||
#ifdef FXCG50
|
||||
if(pos == 0) color = C_RGB(24, 24, 24);
|
||||
#endif
|
||||
drect(x + text_w + scroll_spacing, y1,
|
||||
x + text_w + scroll_spacing + scroll_w - 1, y2,
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
//=== Edition functions ===//
|
||||
|
||||
GINLINE static stredit_t *last_line(console_t *cons)
|
||||
{
|
||||
return linebuf_get_last_line(&cons->lines);
|
||||
}
|
||||
|
||||
bool console_set_cursor(console_t *cons, int pos)
|
||||
{
|
||||
stredit_t *ed = last_line(cons);
|
||||
|
||||
if(pos < ed->prefix || pos > ed->size)
|
||||
return false;
|
||||
|
||||
cons->cursor = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool console_move_cursor(console_t *cons, int cursor_movement)
|
||||
{
|
||||
return console_set_cursor(cons, cons->cursor + cursor_movement);
|
||||
}
|
||||
|
||||
char *console_get_line(console_t *cons, bool copy)
|
||||
{
|
||||
stredit_t *ed = last_line(cons);
|
||||
char *str = stredit_data(ed) + ed->prefix;
|
||||
return copy ? strdup(str) : str;
|
||||
}
|
||||
|
||||
bool console_write_raw(console_t *cons, char const *str, int n)
|
||||
{
|
||||
if(!cons->lines.size)
|
||||
console_newline(cons);
|
||||
|
||||
/* Split string into chunks smaller than each line's storage capacity. */
|
||||
while(n > 0) {
|
||||
stredit_t *ed = last_line(cons);
|
||||
int capacity = stredit_capacity(ed);
|
||||
int round_size = min(n, capacity);
|
||||
|
||||
if(!stredit_insert(ed, cons->cursor, str, round_size))
|
||||
return false;
|
||||
cons->cursor += round_size;
|
||||
cons->render_needed = true;
|
||||
if(round_size < n)
|
||||
console_newline(cons);
|
||||
n -= round_size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool console_write(console_t *cons, char const *buf, int n)
|
||||
{
|
||||
int offset = 0;
|
||||
if(n < 0)
|
||||
n = strlen(buf);
|
||||
|
||||
while(offset < n) {
|
||||
/* Find the first '\n', '\e' or end of buffer */
|
||||
char const *end = buf + offset;
|
||||
while(end < buf + n && *end != '\n' && *end != '\e' && *end != 8)
|
||||
end++;
|
||||
|
||||
int line_size = end - (buf + offset);
|
||||
if(!console_write_raw(cons, buf + offset, line_size))
|
||||
return false;
|
||||
|
||||
offset += line_size;
|
||||
if(offset >= n)
|
||||
break;
|
||||
|
||||
if(buf[offset] == '\n') {
|
||||
console_newline(cons);
|
||||
offset++;
|
||||
}
|
||||
else if(buf[offset] == 8) {
|
||||
offset++;
|
||||
stredit_t *ed = last_line(cons);
|
||||
if(cons->cursor > 0) {
|
||||
stredit_delete(ed, cons->cursor-1, 1);
|
||||
cons->cursor--;
|
||||
}
|
||||
}
|
||||
else if(buf[offset] == '\e') {
|
||||
stredit_t *ed = last_line(cons);
|
||||
offset++;
|
||||
|
||||
/* TODO: Handle more complex escape sequences */
|
||||
if(offset + 2 <= n && buf[offset] == '[' && buf[offset+1] == 'K') {
|
||||
stredit_delete(ed, cons->cursor, ed->size - cons->cursor);
|
||||
offset += 2;
|
||||
}
|
||||
if(offset + 2 <= n && buf[offset] == 1 && buf[offset+1] == 'D') {
|
||||
cons->cursor -= (cons->cursor > 0);
|
||||
}
|
||||
if(offset + 2 <= n && buf[offset] == 1 && buf[offset+1] == 'C') {
|
||||
cons->cursor += (cons->cursor < ed->size);
|
||||
}
|
||||
}
|
||||
|
||||
cons->render_needed = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void console_lock_prefix(console_t *cons)
|
||||
{
|
||||
stredit_set_prefix(last_line(cons), cons->cursor);
|
||||
}
|
||||
|
||||
void console_delete_at_cursor(console_t *cons, int n)
|
||||
{
|
||||
int real_n = stredit_delete(last_line(cons), cons->cursor - n, n);
|
||||
cons->cursor -= real_n;
|
||||
cons->render_needed = true;
|
||||
}
|
||||
|
||||
void console_clear_current_line(console_t *cons)
|
||||
{
|
||||
stredit_t *ed = last_line(cons);
|
||||
stredit_delete(ed, ed->prefix, ed->size - ed->prefix);
|
||||
cons->cursor = ed->prefix;
|
||||
cons->render_needed = true;
|
||||
}
|
||||
|
||||
//=== Terminal input ===//
|
||||
|
||||
int console_key_event_to_char(key_event_t ev)
|
||||
{
|
||||
int key = ev.key;
|
||||
|
||||
if(key == KEY_LEFT && ev.shift)
|
||||
return CHAR_CTRL_A; /* go-to-start-of-line */
|
||||
if(key == KEY_LEFT)
|
||||
return CHAR_CTRL_B; /* go-back-one-char */
|
||||
if(key == KEY_ACON)
|
||||
return CHAR_CTRL_C; /* cancel */
|
||||
if(key == KEY_DEL)
|
||||
return 8; /* delete-at-cursor */
|
||||
if(key == KEY_RIGHT && ev.shift)
|
||||
return CHAR_CTRL_E; /* go-to-end-of-line */
|
||||
if(key == KEY_RIGHT)
|
||||
return CHAR_CTRL_F; /* go-forward-one-char */
|
||||
if(key == KEY_DOWN)
|
||||
return CHAR_CTRL_N; /* go to next line in history */
|
||||
if(key == KEY_UP)
|
||||
return CHAR_CTRL_P; /* go to previous line in history */
|
||||
if(key == KEY_EXIT)
|
||||
return CHAR_CTRL_D; /* eof */
|
||||
if(key == KEY_EXE)
|
||||
return '\r';
|
||||
|
||||
return keymap_translate(key, ev.shift, ev.alpha);
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// ____ PythonExtra //
|
||||
//.-'`_ o `;__, A community port of MicroPython for CASIO calculators. //
|
||||
//.-'` `---` ' License: MIT (except some files; see LICENSE) //
|
||||
//---------------------------------------------------------------------------//
|
||||
// pe.console: Terminal emulator
|
||||
//
|
||||
// This header implements a basic terminal emulator compatible with
|
||||
// MicroPython's readline() implementation.
|
||||
//
|
||||
// The main features are:
|
||||
// * Dynamically-sized lines with reflow
|
||||
// * Cap memory usage based on the total amount of text, not just line count
|
||||
// * Basic ANSI-escape-based edition features (but only on the last line)
|
||||
//
|
||||
// The console tries fairly hard to focus on text manipulation and separate
|
||||
// rendering. To render, one must first compute a "view" of the terminal, which
|
||||
// essentially determines line wrapping and scrolling bounds, and then use that
|
||||
// view and a valid scroll position within it to render.
|
||||
//---
|
||||
|
||||
#ifndef __PYTHONEXTRA_CONSOLE_H
|
||||
#define __PYTHONEXTRA_CONSOLE_H
|
||||
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <stdbool.h>
|
||||
#include "stredit.h"
|
||||
|
||||
/* Maximum line length, to ensure the console can threshold its memory usage
|
||||
while cleaning only entire lines. Lines longer than this get split. */
|
||||
#define PE_CONSOLE_LINE_MAX_LENGTH 1024
|
||||
|
||||
/* Allocation arena for arrays of lines. */
|
||||
// TODO: Split circular buffers
|
||||
#ifdef FX9860G
|
||||
#define PE_CONSOLE_LINE_ALLOC NULL
|
||||
#else
|
||||
#define PE_CONSOLE_LINE_ALLOC NULL
|
||||
#endif
|
||||
|
||||
//=== Static console lines ===//
|
||||
|
||||
/* A line whose contents have been frozen. The only variable left is how many
|
||||
render lines it takes, which is kept at the beginning of the buffer along
|
||||
with its size. */
|
||||
typedef struct
|
||||
{
|
||||
/* Number of non-NUL bytes in data[] (read-only) */
|
||||
uint16_t size;
|
||||
/* Number of render lines occupied by the line (read-write) */
|
||||
uint8_t render_lines;
|
||||
/* Raw NUL-terminated data (read-only) */
|
||||
char data[];
|
||||
|
||||
} console_fline_t;
|
||||
|
||||
/* sizeof(console_fline_t) without alignment */
|
||||
#define CONSOLE_FLINE_SIZE 3
|
||||
|
||||
/* Update the number of render lines for the chosen width. */
|
||||
void console_fline_update_render_lines(console_fline_t *FL, int width);
|
||||
|
||||
/* Render a vertical slice of the wrapped line. */
|
||||
int console_fline_render(int x, int y, console_fline_t *FL, int w, int dy,
|
||||
int show_from, int show_until, int cursor);
|
||||
|
||||
//=== Rotating line storage ===//
|
||||
|
||||
/* linebuf_t: A rotating array of console lines. */
|
||||
typedef struct
|
||||
{
|
||||
/* A rotating array of `capacity` lines starting at position `start` and
|
||||
holding `size` lines. The array is pre-allocated. The last line, if
|
||||
there is one, is stored as NULL and its address is edit->raw. */
|
||||
console_fline_t **lines;
|
||||
/* Editor for the last line. The pointer to the last line is stored there
|
||||
instead of in the `lines` array because it gets reallocated regularly
|
||||
during edition. */
|
||||
stredit_t edit;
|
||||
|
||||
/* Invariants:
|
||||
- capacity > 0
|
||||
- 0 <= size <= capacity
|
||||
- 0 <= start < capacity
|
||||
- When size is 0, start is undefined. */
|
||||
int16_t capacity, start, size;
|
||||
|
||||
/* Total number of rendered lines for the buffer. */
|
||||
int16_t total_rendered;
|
||||
|
||||
/* To keep track of lines' identity, the rotating array includes an extra
|
||||
numbering system. Each line is assigned an *absolute* line number which
|
||||
starts at 1 and increases every time a line is added. That number is
|
||||
independent of rotation.
|
||||
|
||||
Absolute line number of the next line to be removed. This identifies
|
||||
the `start` line, unless the buffer is empty. Regardless, the interval
|
||||
[buf->absolute .. buf->absolute + buf->size) always covers exactly the
|
||||
set of lines that are held in the buffer. */
|
||||
int absolute;
|
||||
|
||||
/* To avoid memory explosion, the rotating array can be set to clean up old
|
||||
lines when the total memory consumption is too high. `backlog_size`
|
||||
specifies how many bytes of text lines are allowed to hold. */
|
||||
int backlog_size;
|
||||
/* Total size of current lines, in bytes, excluding the last line. */
|
||||
int total_size_except_last;
|
||||
|
||||
/* Last absolute line that has been both laid out for rendering and frozen
|
||||
for edition (ie. followed by another line). Lazy layout would start at
|
||||
`absolute_rendered+1`. */
|
||||
int absolute_rendered;
|
||||
|
||||
} linebuf_t;
|
||||
|
||||
/* Initialize a rotating buffer by allocating `line_count` lines. The buffer
|
||||
will allow up to `backlog_size` bytes of text data and clean up lines past
|
||||
that limit. This function does not free pre-existing data in `buf`. */
|
||||
bool linebuf_init(linebuf_t *buf, int capacity, int backlog_size);
|
||||
|
||||
/* Free a rotating buffer and clean it up. */
|
||||
void linebuf_deinit(linebuf_t *buf);
|
||||
|
||||
/* Absolute line numbers of the "start" and "end" of the buffer. The set of
|
||||
lines in the buffer is always [start ... end). If the buffer is empty, the
|
||||
interval is empty and neither line number is in the buffer. */
|
||||
int linebuf_start(linebuf_t const *buf);
|
||||
int linebuf_end(linebuf_t const *buf);
|
||||
|
||||
/* Get a pointer to the line with the given absolute number. */
|
||||
console_fline_t *linebuf_get_line(linebuf_t const *buf, int absolute_number);
|
||||
|
||||
/* Get a pointer to the last line in the buffer (the editable line). */
|
||||
stredit_t *linebuf_get_last_line(linebuf_t *buf);
|
||||
|
||||
/* Add a new line to the buffer (recycling an old one if needed). */
|
||||
stredit_t *linebuf_new_line(linebuf_t *buf);
|
||||
|
||||
/* Recycle the `n` oldest lines from the buffer. */
|
||||
void linebuf_recycle_oldest_lines(linebuf_t *buf, int n);
|
||||
|
||||
/* Clean up lines to try and keep the memory footprint of the text under
|
||||
`backlog_size` bytes. Always keeps at least the last line. */
|
||||
void linebuf_clean_backlog(linebuf_t *buf);
|
||||
|
||||
/* Update the render width computation for all lines in the buffer. If `lazy`
|
||||
is false, all lines are re-laid out. But in the console the width often
|
||||
remains the same for many renders, and only the last line can be edited. In
|
||||
this case, `lazy` can be set to true, and only lines added or edited since
|
||||
the previous render will be re-laid out. */
|
||||
void linebuf_update_render(linebuf_t *buf, int width, bool lazy);
|
||||
|
||||
//=== Terminal emulator ===//
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* A rotating array of console_line_t. Never empty. */
|
||||
linebuf_t lines;
|
||||
|
||||
/* Cursor position within the last line. */
|
||||
int16_t cursor;
|
||||
|
||||
/* Whether new data has been added and a frame should be rendered. */
|
||||
bool render_needed;
|
||||
|
||||
/* View geometry parameters from last console_compute_view(). */
|
||||
font_t const *render_font;
|
||||
int16_t render_width;
|
||||
int16_t render_lines;
|
||||
|
||||
} console_t;
|
||||
|
||||
/* Scroll position measured as a number of lines up from the bottom. */
|
||||
typedef int console_scrollpos_t;
|
||||
|
||||
/* Create a new console with the specified backlog size. */
|
||||
console_t *console_create(int backlog_size, int maximum_line_count);
|
||||
|
||||
/* Create a new empty line at the bottom of the console, and move the cursor
|
||||
there. Previous lines can no longer be edited. */
|
||||
void console_newline(console_t *cons);
|
||||
|
||||
/* Clear the console's render flag, which is used to notify of changes. This
|
||||
function is used when handing control of the display from the console to a
|
||||
Python program so the console doesn't override the program's output. */
|
||||
void console_clear_render_flag(console_t *cons);
|
||||
|
||||
/* Destroy the console and free all associated memory. */
|
||||
void console_destroy(console_t *cons);
|
||||
|
||||
//=== Rendering interface ===//
|
||||
|
||||
/* Compute a view of the console for rendering and scrolling.
|
||||
@font Font to render text with (use to compute line wrapping)
|
||||
@width View width in pixels
|
||||
@lines Number of text lines (spacing can be changed later) */
|
||||
void console_compute_view(console_t *cons, font_t const *font,
|
||||
int width, int lines);
|
||||
|
||||
/* Clamp a scrolling position to the range valid of the last computed view. */
|
||||
console_scrollpos_t console_clamp_scrollpos(console_t const *cons,
|
||||
console_scrollpos_t pos);
|
||||
|
||||
/* Render the console at (x,y). The render `width`, the number of `lines` and
|
||||
the text `font` are all as specified by the latest console_compute_view().
|
||||
`dy` indicates line height. */
|
||||
void console_render(int x, int y, console_t *cons, int dy,
|
||||
console_scrollpos_t pos);
|
||||
|
||||
//=== Edition functions ===//
|
||||
|
||||
/* Set the cursor position within the current line. Returns false if the cursor
|
||||
cannot move there due to bounds. */
|
||||
bool console_set_cursor(console_t *cons, int absolute_cursor_pos);
|
||||
|
||||
/* Move the cursor position within the current line. Returns false if the
|
||||
cursor position didn't change due to bounds. */
|
||||
bool console_move_cursor(console_t *cons, int cursor_movement);
|
||||
|
||||
/* Get the contents of the current line (skipping the prefix). If copy=true,
|
||||
returns a copy created with malloc(), otherwise returns a pointer within the
|
||||
original string. Mind that the original might disappear very quickly (as
|
||||
early as the next console_new_line() due to automatic backlog cleaning). */
|
||||
char *console_get_line(console_t *cons, bool copy);
|
||||
|
||||
/* Write string at the cursor's position within the last line. This writes a
|
||||
raw string without interpreting escape sequences and newlines. */
|
||||
bool console_write_raw(console_t *cons, char const *str, int n);
|
||||
|
||||
/* Write string at the cursor's position within the last line. This function
|
||||
interprets escape sequences and newlines. */
|
||||
bool console_write(console_t *cons, char const *str, int n);
|
||||
|
||||
/* Set the current cursor position to mark the prefix of the current line. */
|
||||
void console_lock_prefix(console_t *cons);
|
||||
|
||||
/* Delete n characters from the cursor position. */
|
||||
void console_delete_at_cursor(console_t *cons, int n);
|
||||
|
||||
/* Clear the current line. */
|
||||
void console_clear_current_line(console_t *cons);
|
||||
|
||||
//=== Input method ===//
|
||||
|
||||
/* Interpret a key event into a terminal input. This is a pretty raw input
|
||||
method with no shift/alpha lock, kept for legacy as a VT-100-style terminal
|
||||
emulator. */
|
||||
int console_key_event_to_char(key_event_t ev);
|
||||
|
||||
#endif /* __PYTHONEXTRA_CONSOLE_H */
|
|
@ -0,0 +1,232 @@
|
|||
#include "debug.h"
|
||||
#include <gint/usb.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <gint/kmalloc.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/timer.h>
|
||||
#include <gint/cpu.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "py/mpstate.h"
|
||||
|
||||
void pe_debug_panic(char const *msg)
|
||||
{
|
||||
int dy = dfont_default()->line_height + 2;
|
||||
|
||||
dclear(C_BLACK);
|
||||
dtext(1, 1, C_WHITE, "PythonExtra panic!");
|
||||
dtext(1, 1+dy, C_WHITE, msg);
|
||||
dupdate();
|
||||
|
||||
getkey();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct pe_debug_meminfo pe_debug_startup_meminfo[PE_DEBUG_STARTUP_N];
|
||||
|
||||
void pe_debug_get_meminfo(struct pe_debug_meminfo *info)
|
||||
{
|
||||
kmalloc_gint_stats_t *s;
|
||||
|
||||
#ifdef FX9860G
|
||||
s = kmalloc_get_gint_stats(kmalloc_get_arena("_uram"));
|
||||
info->_uram_used = s->used_memory;
|
||||
info->_uram_free = s->free_memory;
|
||||
|
||||
s = kmalloc_get_gint_stats(kmalloc_get_arena("pram0"));
|
||||
info->pram0_used = s->used_memory;
|
||||
info->pram0_free = s->free_memory;
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
s = kmalloc_get_gint_stats(kmalloc_get_arena("_uram"));
|
||||
info->_uram_used = s->used_memory;
|
||||
info->_uram_free = s->free_memory;
|
||||
|
||||
s = kmalloc_get_gint_stats(kmalloc_get_arena("_ostk"));
|
||||
info->_ostk_used = s->used_memory;
|
||||
info->_ostk_free = s->free_memory;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pe_debug_browse_meminfo(void)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
struct pe_debug_meminfo infonow;
|
||||
pe_debug_get_meminfo(&infonow);
|
||||
|
||||
#ifdef FX9860G
|
||||
static char const * const names[] = {
|
||||
"main", "cons.", "upy", "prom.", "ui",
|
||||
"now", /* extra element compared to original enum */
|
||||
};
|
||||
dprint(1, 0, C_BLACK, "Memory info");
|
||||
|
||||
extern font_t font_3x5, font_4x6;
|
||||
font_t const *old_font = dfont(&font_4x6);
|
||||
dtext(33, 9, C_BLACK, "_uram");
|
||||
dtext(75, 9, C_BLACK, "pram0");
|
||||
dline(2, 16, DWIDTH-3, 16, C_BLACK);
|
||||
|
||||
for(int i = 0; i < PE_DEBUG_STARTUP_N + 1; i++) {
|
||||
int y = 7 * i + 18;
|
||||
struct pe_debug_meminfo *info = &pe_debug_startup_meminfo[i];
|
||||
if(i >= PE_DEBUG_STARTUP_N) {
|
||||
dline(2, y, DWIDTH-3, y, C_BLACK);
|
||||
y += 2;
|
||||
info = &infonow;
|
||||
}
|
||||
|
||||
dtext(2, y, C_BLACK, names[i]);
|
||||
dfont(&font_3x5);
|
||||
dprint(33, y+1, C_BLACK,
|
||||
"%d,%d", info->_uram_used, info->_uram_free);
|
||||
dprint(75, y+1, C_BLACK,
|
||||
"%d,%d", info->pram0_used, info->pram0_free);
|
||||
dfont(&font_4x6);
|
||||
}
|
||||
|
||||
dfont(old_font);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
static char const * const names[] = {
|
||||
"main", "console", "upy", "prompt", "ui",
|
||||
"now", /* extra element compared to original enum */
|
||||
};
|
||||
|
||||
dtext(1, 1, C_BLACK, "Memory info");
|
||||
dtext(83, 24, C_BLACK, "_uram");
|
||||
dtext(170, 24, C_BLACK, "_ostk");
|
||||
dline(10, 36, DWIDTH-11, 36, C_BLACK);
|
||||
|
||||
for(int i = 0; i < PE_DEBUG_STARTUP_N + 1; i++) {
|
||||
int y = 15 * i + 39;
|
||||
struct pe_debug_meminfo *info = &pe_debug_startup_meminfo[i];
|
||||
if(i >= PE_DEBUG_STARTUP_N) {
|
||||
dline(10, y, DWIDTH-11, y, C_BLACK);
|
||||
y += 4;
|
||||
info = &infonow;
|
||||
}
|
||||
|
||||
dtext(10, y, C_BLACK, names[i]);
|
||||
dprint(83, y+1, C_BLACK,
|
||||
"%d,%d", info->_uram_used, info->_uram_free);
|
||||
dprint(170, y+1, C_BLACK,
|
||||
"%d,%d", info->_ostk_used, info->_ostk_free);
|
||||
}
|
||||
#endif
|
||||
|
||||
dupdate();
|
||||
while((getkey().key) != KEY_EXIT);
|
||||
}
|
||||
|
||||
#if PE_DEBUG
|
||||
|
||||
#if 0 // Timeout fxlink not supported yet
|
||||
static bool timeout_popup(void)
|
||||
{
|
||||
dclear(C_BLACK);
|
||||
dtext_opt(DWIDTH/2, DHEIGHT/2 - 21, C_WHITE, C_NONE, DTEXT_MIDDLE,
|
||||
DTEXT_MIDDLE, "An fxlink message timed out!");
|
||||
dtext_opt(DWIDTH/2, DHEIGHT/2 - 7, C_WHITE, C_NONE, DTEXT_MIDDLE,
|
||||
DTEXT_MIDDLE, "Start fxlink and press [EXE]:");
|
||||
dtext_opt(DWIDTH/2, DHEIGHT/2 + 7, C_WHITE, C_NONE, DTEXT_MIDDLE,
|
||||
DTEXT_MIDDLE, "% fxlink -iqw");
|
||||
dtext_opt(DWIDTH/2, DHEIGHT/2 + 21, C_WHITE, C_NONE, DTEXT_MIDDLE,
|
||||
DTEXT_MIDDLE, "or press [EXIT] to drop the message");
|
||||
dupdate();
|
||||
|
||||
while(1) {
|
||||
int key = getkey().key;
|
||||
if(key == KEY_EXE)
|
||||
return false;
|
||||
if(key == KEY_EXIT)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool videocapture = false;
|
||||
|
||||
void pe_debug_init(void)
|
||||
{
|
||||
usb_interface_t const *intf[] = { &usb_ff_bulk, NULL };
|
||||
usb_open(intf, GINT_CALL_NULL);
|
||||
usb_open_wait();
|
||||
}
|
||||
|
||||
int pe_debug_printf(char const *fmt, ...)
|
||||
{
|
||||
char str[512];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
int rc = vsnprintf(str, sizeof str, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
usb_open_wait();
|
||||
usb_fxlink_text(str, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* This function is used in MicroPython. */
|
||||
int DEBUG_printf(char const *fmt, ...)
|
||||
__attribute__((alias("pe_debug_printf")));
|
||||
|
||||
static void print_strn(void *env, const char *str, size_t len) {
|
||||
(void)env;
|
||||
usb_open_wait();
|
||||
usb_fxlink_text(str, len);
|
||||
}
|
||||
|
||||
mp_print_t const mp_debug_print = { NULL, print_strn };
|
||||
|
||||
void pe_debug_kmalloc(char const *prefix)
|
||||
{
|
||||
kmalloc_gint_stats_t *s1, *s2;
|
||||
s1 = kmalloc_get_gint_stats(kmalloc_get_arena("_uram"));
|
||||
|
||||
#ifdef FX9860G
|
||||
s2 = kmalloc_get_gint_stats(kmalloc_get_arena("pram0"));
|
||||
pe_debug_printf("%s: _uram[used=%d free=%d] pram0[used=%d free=%d]\n",
|
||||
prefix,
|
||||
s1->used_memory, s1->free_memory,
|
||||
s2->used_memory, s2->free_memory);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
s2 = kmalloc_get_gint_stats(kmalloc_get_arena("_ostk"));
|
||||
pe_debug_printf("%s: _uram[used=%d free=%d] _ostk[used=%d free=%d]\n",
|
||||
prefix,
|
||||
s1->used_memory, s1->free_memory,
|
||||
s2->used_memory, s2->free_memory);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pe_debug_screenshot(void)
|
||||
{
|
||||
usb_open_wait();
|
||||
usb_fxlink_screenshot(true);
|
||||
}
|
||||
|
||||
void pe_debug_toggle_videocapture(void)
|
||||
{
|
||||
videocapture = !videocapture;
|
||||
}
|
||||
|
||||
void pe_debug_run_videocapture(void)
|
||||
{
|
||||
if(videocapture) {
|
||||
usb_open_wait();
|
||||
usb_fxlink_videocapture(true);
|
||||
}
|
||||
}
|
||||
|
||||
void pe_debug_close(void)
|
||||
{
|
||||
usb_close();
|
||||
}
|
||||
|
||||
#endif /* PE_DEBUG */
|
|
@ -0,0 +1,101 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// ____ PythonExtra //
|
||||
//.-'`_ o `;__, A community port of MicroPython for CASIO calculators. //
|
||||
//.-'` `---` ' License: MIT (except some files; see LICENSE) //
|
||||
//---------------------------------------------------------------------------//
|
||||
// pe.debug: Debugging utilities
|
||||
//
|
||||
// Most of the debugging occurs via USB. This module also includes screenshots
|
||||
// and other developer-only utilities. The interface always exists but it's
|
||||
// almost entirely no-oped if PE_DEBUG isn't set.
|
||||
//---
|
||||
|
||||
#ifndef __PYTHONEXTRA_DEBUG_H
|
||||
#define __PYTHONEXTRA_DEBUG_H
|
||||
|
||||
/* PE_DEBUG is set in mpconfigport.h. */
|
||||
#include "mpconfigport.h"
|
||||
|
||||
/* Initialize debugging resources (mostly the USB connection). */
|
||||
void pe_debug_init(void);
|
||||
|
||||
/* Panic with a message (available even if PE_DEBUG=0). */
|
||||
void pe_debug_panic(char const *msg)
|
||||
__attribute__((noreturn));
|
||||
|
||||
/*** Memory watch utilities (enabled even when PE_DEBUG=0) ***/
|
||||
|
||||
#ifdef FX9860G
|
||||
struct pe_debug_meminfo {
|
||||
uint16_t _uram_used, _uram_free;
|
||||
uint32_t pram0_used, pram0_free;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
struct pe_debug_meminfo {
|
||||
uint16_t _uram_used, _uram_free;
|
||||
uint32_t _ostk_used, _ostk_free;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* Just after entering main() */
|
||||
PE_DEBUG_STARTUP_MAIN,
|
||||
/* After allocating console */
|
||||
PE_DEBUG_STARTUP_CONSOLE,
|
||||
/* After initializing MicroPython */
|
||||
PE_DEBUG_STARTUP_UPY,
|
||||
/* After printing the first prompt */
|
||||
PE_DEBUG_STARTUP_PROMPT,
|
||||
/* After allocating and initializing the GUI */
|
||||
PE_DEBUG_STARTUP_UI,
|
||||
|
||||
PE_DEBUG_STARTUP_N,
|
||||
};
|
||||
|
||||
/* Fetch data about current memory statistics. */
|
||||
void pe_debug_get_meminfo(struct pe_debug_meminfo *info);
|
||||
|
||||
/* Buffer for storing meminfo during startup. */
|
||||
extern struct pe_debug_meminfo pe_debug_startup_meminfo[PE_DEBUG_STARTUP_N];
|
||||
|
||||
#define pe_debug_get_startup_meminfo(NAME) \
|
||||
pe_debug_get_meminfo(&pe_debug_startup_meminfo[PE_DEBUG_STARTUP_ ## NAME])
|
||||
|
||||
/* Browse memory info through a GUI. */
|
||||
void pe_debug_browse_meminfo(void);
|
||||
|
||||
/*** Debugging functions enabled only when PE_DEBUG=1 ***/
|
||||
|
||||
/* Print to the debug stream. This function is also called DEBUG_printf in
|
||||
MicroPython code. */
|
||||
int pe_debug_printf(char const *fmt, ...);
|
||||
|
||||
/* Print information about allocation status. */
|
||||
void pe_debug_kmalloc(char const *prefix);
|
||||
|
||||
/* Take a screenshot. */
|
||||
void pe_debug_screenshot(void);
|
||||
|
||||
/* Toggle video capture. */
|
||||
void pe_debug_toggle_videocapture(void);
|
||||
|
||||
/* Send a video capture frame if video capture is enabled. */
|
||||
void pe_debug_run_videocapture(void);
|
||||
|
||||
/* Close the debugging ressources */
|
||||
void pe_debug_close(void);
|
||||
|
||||
#if !PE_DEBUG
|
||||
#define PE_DEBUG_NOOP do {} while(0)
|
||||
#define pe_debug_init(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_printf(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_kmalloc(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_screenshot(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_toggle_videocapture(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_run_videocapture(...) PE_DEBUG_NOOP
|
||||
#define pe_debug_close(...) PE_DEBUG_NOOP
|
||||
#endif
|
||||
|
||||
#endif /* __PYTHONEXTRA_DEBUG_H */
|
|
@ -0,0 +1,221 @@
|
|||
from gint import *
|
||||
|
||||
#---
|
||||
|
||||
from math import sin, cos, pi
|
||||
from random import randint
|
||||
|
||||
pattern = 2
|
||||
def world(z0, dir, r=None):
|
||||
r = randint(1, 3)
|
||||
r = 3
|
||||
if r == 1:
|
||||
return world_red(z0, dir)
|
||||
elif r == 2:
|
||||
return world_green(z0, dir)
|
||||
elif r == 3:
|
||||
return world_blue(z0, dir)
|
||||
|
||||
def world_red(z0, dir):
|
||||
length = randint(2, 4)
|
||||
platforms = [None] * (length * 8)
|
||||
for i in range(length):
|
||||
for direction in range(4):
|
||||
platforms[8*i+direction] = [0, direction, z0+8*i, z0+8*i+8, 2]
|
||||
for j in range(4):
|
||||
obstacle = randint(0,3)
|
||||
platforms[8*i+4+j] = [1, obstacle, z0+8*i+2*j+1, z0+8*i+2*j+1, 2]
|
||||
return platforms, z0+length*8, (obstacle+1)&3
|
||||
|
||||
def world_green(z0, dir):
|
||||
length = randint(8, 16)
|
||||
platforms = [None] * length
|
||||
for i in range(length):
|
||||
platforms[i] = [0, dir, z0+4+2*i, z0+8+2*i, 3]
|
||||
dir = (dir - randint(1,2)) & 3
|
||||
platforms[0][2] = z0
|
||||
return platforms, z0+(length-1)*2+8, dir
|
||||
|
||||
def world_blue(z0, dir):
|
||||
platforms = []
|
||||
for i in range(16):
|
||||
platforms.append([0, dir, z0+2*i, z0+4+2*i, 4])
|
||||
if i <= 14 and randint(0,2) == 0:
|
||||
bait = (dir + randint(1,3)) & 3
|
||||
platforms.append([0, bait, z0+2*i, z0+6+2*i, 4])
|
||||
platforms.append([1, bait, z0+3+2*i, z0+3+2*i, 4])
|
||||
dir = (dir - randint(1,2)) & 3
|
||||
return platforms, z0+34, dir
|
||||
|
||||
def safe_position(platforms, z, direction):
|
||||
supported = False
|
||||
# Messed up direction encoding
|
||||
if direction & 1:
|
||||
direction = direction ^ 2
|
||||
for (kind, dir, z1, z2, color) in platforms:
|
||||
if dir != direction:
|
||||
continue
|
||||
if kind == 1 and z > z1-1 and z < z2:
|
||||
return False
|
||||
if kind == 0 and z > z1-0.5 and z < z2:
|
||||
supported = True
|
||||
return supported
|
||||
|
||||
def gen_vertices(platforms, index):
|
||||
vertices = []
|
||||
for (kind, direction, z1, z2, color) in platforms:
|
||||
if kind == 0:
|
||||
vertices.append([-4,-3,z1,index])
|
||||
vertices.append([-4, 3,z1,index])
|
||||
vertices.append([-4, 3,z2,index])
|
||||
vertices.append([-4,-3,z2,index])
|
||||
elif kind == 1:
|
||||
vertices.append([-3,-.5,z1,index])
|
||||
vertices.append([-2, .5,z1,index])
|
||||
vertices.append([-3, .5,z1,index])
|
||||
vertices.append([-2,-.5,z1,index])
|
||||
index += 1
|
||||
|
||||
return vertices
|
||||
|
||||
def platform_rotation(vertices, platforms, world_offset):
|
||||
for i in range(len(vertices)):
|
||||
x, y, z, p = vertices[i]
|
||||
dir = platforms[p+world_offset][1]
|
||||
c = (dir == 1) - (dir == 3)
|
||||
s = (dir == 2) - (dir == 0)
|
||||
vertices[i] = [c*x+s*y,s*x+c*y, z, p]
|
||||
|
||||
def transform3d(vertices, theta, camera_z, rotate, flip):
|
||||
theta -= rotate * pi / 14
|
||||
f = 1 - flip / 3.5
|
||||
s, c = sin(theta), cos(theta)
|
||||
|
||||
for i in range(len(vertices)):
|
||||
x, y, z, p = vertices[i]
|
||||
vertices[i] = [(c*x-s*y)*f,(s*x+c*y)*f,(z-camera_z)*2,p]
|
||||
|
||||
def draw_line(p1, p2, color):
|
||||
if p1[2] <= 1:
|
||||
p1, p2 = p2, p1
|
||||
if p1[2] <= 1:
|
||||
return
|
||||
if p2[2] <= 1:
|
||||
t = (p1[2] - 1) / (p1[2] - p2[2])
|
||||
p2[0] = p1[0] + t * (p2[0] - p1[0])
|
||||
p2[1] = p1[1] + t * (p2[1] - p1[1])
|
||||
p2[2] = 1
|
||||
|
||||
x = 196 + int(75 * p1[0] / p1[2])
|
||||
y = 112 + int(75 * p1[1] / p1[2])
|
||||
|
||||
x2 = 196 + int(75 * p2[0] / p2[2])
|
||||
y2 = 112 + int(75 * p2[1] / p2[2])
|
||||
|
||||
dline(x, y, x2, y2, color)
|
||||
|
||||
def draw_scene(vertices, platforms, world_offset, colors, z, score,
|
||||
clear=False):
|
||||
if clear:
|
||||
drect(163, 153, 220, 165, colors[0])
|
||||
|
||||
maxdepth = min(len(vertices), 48)
|
||||
i = 0
|
||||
while i < len(vertices):
|
||||
if vertices[i][2] > 16:
|
||||
break
|
||||
p = platforms[vertices[i][3]+world_offset]
|
||||
c = colors[0 if clear else p[4]]
|
||||
|
||||
if p[0] == 0:
|
||||
draw_line(vertices[i], vertices[i+1], c)
|
||||
draw_line(vertices[i+1], vertices[i+2], c)
|
||||
draw_line(vertices[i+2], vertices[i+3], c)
|
||||
draw_line(vertices[i+3], vertices[i], c)
|
||||
i += 4
|
||||
elif p[0] == 1:
|
||||
draw_line(vertices[i], vertices[i+1], c)
|
||||
draw_line(vertices[i+2], vertices[i+3], c)
|
||||
i += 4
|
||||
|
||||
if not clear:
|
||||
dtext_opt(DWIDTH//2, DHEIGHT-15, colors[1], colors[0], DTEXT_CENTER,
|
||||
DTEXT_BOTTOM, " " + str(score) + " ", -1)
|
||||
|
||||
dtext_opt(DWIDTH//2, 15, colors[1], colors[0], DTEXT_CENTER, DTEXT_BOTTOM,
|
||||
"Chute tridimensionnelle", -1)
|
||||
|
||||
colors_light = [
|
||||
0xffff, # White
|
||||
0x0000, # Black
|
||||
0xc000, # Dark red
|
||||
0x0480, # Dark green
|
||||
0x0018, # Dark blue
|
||||
]
|
||||
colors_dark = [
|
||||
0x0000, # Black
|
||||
0xffff, # White
|
||||
0xfd14, # Light red
|
||||
0x87f0, # Light green
|
||||
0xa51f, # Light blue
|
||||
]
|
||||
colors = colors_light
|
||||
|
||||
dclear(colors[0])
|
||||
|
||||
z = 0
|
||||
score = 0
|
||||
vertices = []
|
||||
direction = 0
|
||||
rotate = 0
|
||||
flip = 0
|
||||
|
||||
world_platforms, world_end, world_dir = world_green(z, direction)
|
||||
world_offset = 0
|
||||
|
||||
while True:
|
||||
if colors == colors_light and score >= 333:
|
||||
dclear(colors_dark[0])
|
||||
colors = colors_dark
|
||||
else:
|
||||
draw_scene(vertices, world_platforms, world_offset, colors, z,
|
||||
score, True)
|
||||
|
||||
vertices = gen_vertices(world_platforms, -world_offset)
|
||||
platform_rotation(vertices, world_platforms, world_offset)
|
||||
transform3d(vertices, direction * pi / 2, z, rotate, flip)
|
||||
draw_scene(vertices, world_platforms, world_offset, colors, z, score)
|
||||
dupdate()
|
||||
|
||||
if z >= world_platforms[0][3]:
|
||||
world_platforms.pop(0)
|
||||
world_offset -= 1
|
||||
if len(world_platforms) < 16:
|
||||
p, world_end, world_dir = world(world_end, world_dir)
|
||||
world_platforms += p
|
||||
|
||||
z += .25
|
||||
|
||||
if rotate or flip:
|
||||
pass
|
||||
elif safe_position(world_platforms, z, direction):
|
||||
score += 1
|
||||
else:
|
||||
score += 1#max(score - 8, 0)
|
||||
|
||||
rotate -= (rotate > 0)
|
||||
flip -= (flip > 0)
|
||||
|
||||
while 1:
|
||||
ev = pollevent()
|
||||
if ev.type == KEYEV_NONE:
|
||||
break
|
||||
|
||||
if ev.type == KEYEV_DOWN and ev.key in [KEY_SHIFT, KEY_EXE, KEY_RIGHT]:
|
||||
if rotate >= 5:
|
||||
direction = (direction + 1) & 3
|
||||
flip = rotate
|
||||
rotate = 0
|
||||
elif rotate == 0:
|
||||
direction = (direction + 1) & 3
|
||||
rotate = 7
|
|
@ -0,0 +1,253 @@
|
|||
from casioplot import *
|
||||
from gint import *
|
||||
from random import randint
|
||||
|
||||
#--------------------
|
||||
#config graphiq Casio
|
||||
#--------------------
|
||||
# pour Graph 90+E
|
||||
|
||||
L_FENETRE=396 #largeur de la zone graphique affichable
|
||||
H_FENETRE=224 #hauteur de la zone graphique affichable
|
||||
|
||||
#dimensions des caracteres des polices
|
||||
LNUMH_POLICE = {"small":(8,10), "medium":(12,17), "large": (18,23)}
|
||||
|
||||
POLICE="small" #taille de police (small, medium ou large)
|
||||
H_POLICE = LNUMH_POLICE[POLICE][1] #hauteur des caracteres de la police
|
||||
LNUM_POLICE = LNUMH_POLICE[POLICE][0] #largeur des caracteres numeriques de la police
|
||||
|
||||
#-------------------
|
||||
# config graphiq jeu
|
||||
#-------------------
|
||||
HMIN_TUYAU=16 #hauteur minimale des tuyaux
|
||||
H_SOL=H_POLICE+4 #hauteur du sol
|
||||
L_TUYAU=32 #largeur des tuyaux
|
||||
H_FOND=H_FENETRE-H_SOL #hauteur du fond
|
||||
L_FBIRD,H_FBIRD=17,12 #largeur et hauteur de Flappy Bird
|
||||
D_FBIRD=64 #position initiale de Flappy Bird
|
||||
INTH_TUYAUX=144 #espacement horizontal entre les posititions de deux tuyaux consecutifs
|
||||
INTVMIN_TUYAUX=64 #espacement vertical minimal entre les pays de tuyaux
|
||||
|
||||
#------------------
|
||||
# outils graphiques
|
||||
#------------------
|
||||
# extension casioplot
|
||||
|
||||
def draw_prect(x,y,w,h,c):
|
||||
"""dessine un rectangle plein
|
||||
de largeur w,hauteur h et couleur c
|
||||
avec le coin superieur gauche de coordonnees (x;y)
|
||||
"""
|
||||
drect(x,y,x+w-1,y+h-1,c)
|
||||
|
||||
#################
|
||||
# FONCTIONS JEU #
|
||||
#################
|
||||
|
||||
def ajoute_tuyau():
|
||||
global d_tuyaux,hinf_tuyaux,hsup_tuyaux
|
||||
d_tuyaux.append(d_tuyaux[-1]+INTH_TUYAUX)
|
||||
hinf_tuyau=randint(HMIN_TUYAU,H_FOND-INTVMIN_TUYAUX-HMIN_TUYAU)
|
||||
hsup_tuyau=randint(HMIN_TUYAU,H_FOND-hinf_tuyau-INTVMIN_TUYAUX)
|
||||
hinf_tuyaux.append(hinf_tuyau)
|
||||
hsup_tuyaux.append(hsup_tuyau)
|
||||
|
||||
def simulation():
|
||||
global d_fenetre, d_fbird, d_fbird_ancien, alt_fbird, alt_fbird_ancien, vx_fbird, vy_fbird, score
|
||||
if d_fenetre+L_FENETRE >= d_tuyaux[-1]+INTH_TUYAUX:
|
||||
ajoute_tuyau()
|
||||
# le score correspond a l'index du tuyau a tester
|
||||
if d_tuyaux[score]+L_TUYAU<d_fbird:
|
||||
score+=1
|
||||
if vx_fbird>0 and collision_fbird():
|
||||
vx_fbird=0
|
||||
if vy_fbird>0:
|
||||
vy_fbird=0
|
||||
draw_sol()
|
||||
if vx_fenetre != 0 and vx_fbird != 0:
|
||||
d_fenetre -= vx_fenetre
|
||||
d_fbird_ancien,alt_fbird_ancien=d_fbird,alt_fbird
|
||||
d_fbird += vx_fbird
|
||||
alt_fbird = max(H_FBIRD,alt_fbird+vy_fbird)
|
||||
vy_fbird += dy_gravite
|
||||
|
||||
#------------------
|
||||
# fonctions graphiq
|
||||
#------------------
|
||||
|
||||
PALETTE = [0x0000, 0x7518, 0xce18, 0xd5e4, 0xe402, 0xea87, 0xeffb]
|
||||
BIRD_IMG = [
|
||||
" ###### ",
|
||||
" ##...#__# ",
|
||||
" #..::#____# ",
|
||||
" ####:::#___#_# ",
|
||||
"#....#::#___#_# ",
|
||||
"#.....#::#____# ",
|
||||
"#:...:#:::######",
|
||||
" #:::#:::#======",
|
||||
" ###+++#=######",
|
||||
" #++++++#=====#",
|
||||
" ##+++++##### ",
|
||||
" ##### "]
|
||||
|
||||
# traduction des caractères en couleurs
|
||||
BIRD = [[PALETTE["# .:+=_".index(c)] for c in line] for line in BIRD_IMG]
|
||||
|
||||
COULEUR_BORD,COULEUR_FOND,COULEUR_SOL,COULEUR_TUYAU=0x0000,0x7518,0xb4e8,0x2462
|
||||
|
||||
def y_altitude(alt):
|
||||
"""retourne la position verticale d'affichage
|
||||
d'un objet situe a l'altitude alt
|
||||
"""
|
||||
return H_FOND-alt
|
||||
|
||||
def redraw_prect(x,y,l,h,cint,credraw):
|
||||
"""refraichit l'affichage d'un rectangle plein
|
||||
en redessinant uniquement ses extremites gauche et droite
|
||||
"""
|
||||
y2 = y+h-1
|
||||
drect(x,y,x+1,y2,cint)
|
||||
drect(x+l,y,x+l+1,y2,credraw)
|
||||
|
||||
def draw_tuyaux(x, hinf, hsup):
|
||||
"""affiche une paire de tuyaux
|
||||
de hinf de hauteur pour le tuyau inferieur
|
||||
de hsup de hauteur pour le tuyau superieur
|
||||
avec x comme limite gauche
|
||||
"""
|
||||
yinf=y_altitude(hinf)
|
||||
draw_prect(x+3,0,L_TUYAU-6,hsup-12,COULEUR_TUYAU)
|
||||
draw_prect(x,hsup-12,L_TUYAU,12,COULEUR_TUYAU)
|
||||
draw_prect(x,yinf,L_TUYAU,12,COULEUR_TUYAU)
|
||||
draw_prect(x+3,yinf+12,L_TUYAU-6,hinf-12,COULEUR_TUYAU)
|
||||
|
||||
def redraw_tuyaux(x, hinf, hsup):
|
||||
"""efface l'affichage precedent puis dessine une paire de tuyaux
|
||||
de hinf de hauteur pour le tuyau inferieur
|
||||
de hsup de hauteur pour le tuyau superieur
|
||||
avec x comme limite gauche
|
||||
apres effacement de l'affichage precedent
|
||||
"""
|
||||
yinf=y_altitude(hinf)
|
||||
redraw_prect(x+3,0,L_TUYAU-6,hsup-12,COULEUR_TUYAU,COULEUR_FOND)
|
||||
redraw_prect(x,hsup-12,L_TUYAU,12,COULEUR_TUYAU,COULEUR_FOND)
|
||||
redraw_prect(x,yinf,L_TUYAU,12,COULEUR_TUYAU,COULEUR_FOND)
|
||||
redraw_prect(x+3,yinf+12,L_TUYAU-6,hinf-12,COULEUR_TUYAU,COULEUR_FOND)
|
||||
|
||||
def redraw_fbird(x,y,x_ancien,y_ancien):
|
||||
"""dessine Flappy Bird
|
||||
dans un rectangle de 17*12 pixels
|
||||
de coin superieur gauche (x;y)
|
||||
"""
|
||||
draw_prect(x_ancien+1,round(y_ancien),L_FBIRD,H_FBIRD,COULEUR_FOND)
|
||||
y=round(y)
|
||||
for ligne in range(12):
|
||||
for col in range(16):
|
||||
dpixel(x+col, y+ligne, BIRD[ligne][col])
|
||||
|
||||
def draw_sol():
|
||||
draw_prect(0,H_FOND,L_FENETRE,H_SOL,COULEUR_SOL)
|
||||
if vx_fenetre==0:
|
||||
info="[SHIFT]: Demarrer"
|
||||
elif vx_fbird!=0:
|
||||
info="[SHIFT]: Battre des ailes"
|
||||
else:
|
||||
info="[SHIFT]: Quitter"
|
||||
dtext(1,H_FENETRE-H_POLICE-2,COULEUR_BORD,info)
|
||||
|
||||
def draw_jeu():
|
||||
"""initialise l'affichage en dessinant
|
||||
l'ensemble des elements graphiques
|
||||
"""
|
||||
dclear(COULEUR_FOND)
|
||||
redraw_fbird(d_fbird-d_fenetre,y_altitude(alt_fbird),d_fbird_ancien-d_fenetre,y_altitude(alt_fbird_ancien))
|
||||
for k in range(score-1,len(d_tuyaux)):
|
||||
d_tuyau=d_tuyaux[k]
|
||||
if d_tuyau+L_TUYAU >= d_fenetre and d_tuyau < d_fenetre+L_FENETRE:
|
||||
draw_tuyaux(d_tuyau-d_fenetre,hinf_tuyaux[k],hsup_tuyaux[k])
|
||||
draw_sol()
|
||||
|
||||
def redraw_score():
|
||||
ch_score=str(score)
|
||||
l_score=LNUM_POLICE*len(ch_score)
|
||||
x_score=L_FENETRE-l_score
|
||||
y_score=H_FENETRE-H_POLICE-2
|
||||
draw_prect(x_score,y_score,l_score,H_POLICE,COULEUR_SOL)
|
||||
dtext(x_score,y_score,COULEUR_BORD,ch_score)
|
||||
|
||||
def redraw_jeu():
|
||||
"""rafraichit l'affichage en redessinant
|
||||
les seuls elements graphiques modifies
|
||||
"""
|
||||
redraw_fbird(d_fbird-d_fenetre,y_altitude(alt_fbird),d_fbird_ancien-d_fenetre,y_altitude(alt_fbird_ancien))
|
||||
for k in range(score-1,len(d_tuyaux)):
|
||||
d_tuyau=d_tuyaux[k]
|
||||
if d_tuyau+L_TUYAU >= d_fenetre and d_tuyau < d_fenetre+L_FENETRE:
|
||||
redraw_tuyaux(d_tuyau-d_fenetre,hinf_tuyaux[k],hsup_tuyaux[k])
|
||||
redraw_score()
|
||||
|
||||
def isect_rect(x1,y1,w1,h1,x2,y2,w2,h2):
|
||||
"""teste si il y a une intersection entre les
|
||||
rectangle de largeur w1 hauteur h1 et coin superieur gauche (x1,y1)
|
||||
rectangle de largeur w2 hauteur h2 et coin superieur gauche (x2,y2)
|
||||
"""
|
||||
max_gauche=max(x1,x2)
|
||||
min_droit=min(x1+w1,x2+w2)
|
||||
max_haut=max(y1,y2)
|
||||
min_bas=min(y1+h1,y2+h2)
|
||||
return max_gauche<=min_droit and max_haut<=min_bas
|
||||
|
||||
def collision_fbird():
|
||||
#le score (nombre de tuyaux franchis)
|
||||
#correspond a l'index du tuyau a tester
|
||||
d_tuyau=d_tuyaux[score]
|
||||
hinf_tuyau=hinf_tuyaux[score]
|
||||
hsup_tuyau=hsup_tuyaux[score]
|
||||
#test intersection tuyau inferieur
|
||||
y_fbird=y_altitude(alt_fbird)
|
||||
isect_inf=isect_rect(d_tuyau,y_altitude(hinf_tuyau),L_TUYAU,hinf_tuyau,d_fbird,y_fbird,L_FBIRD,H_FBIRD)
|
||||
#test intersection tuyau superieur
|
||||
isect_sup=isect_rect(d_tuyau,y_fbird,L_TUYAU,hsup_tuyau-y_fbird,d_fbird,y_fbird,L_FBIRD,H_FBIRD)
|
||||
return isect_inf or isect_sup
|
||||
|
||||
d_tuyaux=[L_FENETRE//2] #emplacements horizontaux des tuyaux
|
||||
hinf_tuyaux=[HMIN_TUYAU+20] #hauteurs des tuyaux inferieurs
|
||||
hsup_tuyaux=[HMIN_TUYAU+20] #hauteurs des tuyaux superieurs
|
||||
score = 0 # nombre de tuyaux franchis
|
||||
|
||||
#---------
|
||||
# etat jeu
|
||||
#---------
|
||||
d_fbird,alt_fbird=D_FBIRD,H_FOND
|
||||
d_fbird_ancien,alt_fbird_ancien=d_fbird,alt_fbird
|
||||
vx_fbird,vy_fbird= 2,0
|
||||
dy_gravite = -0.18
|
||||
d_fenetre=0
|
||||
vx_fenetre=0
|
||||
|
||||
def action():
|
||||
global vx_fenetre, vy_fbird
|
||||
if vx_fenetre==0:
|
||||
vx_fenetre=-2
|
||||
draw_sol()
|
||||
elif vx_fbird!=0:
|
||||
vy_fbird=4
|
||||
else:
|
||||
raise SystemExit
|
||||
|
||||
ajoute_tuyau()
|
||||
draw_jeu()
|
||||
while True:
|
||||
redraw_jeu()
|
||||
dupdate()
|
||||
simulation()
|
||||
while 1:
|
||||
e = pollevent()
|
||||
if e.type == KEYEV_NONE:
|
||||
break
|
||||
if e.type == KEYEV_DOWN and e.key in [KEY_EXE, KEY_UP, KEY_SHIFT]:
|
||||
action()
|
||||
|
||||
print("score:")
|
||||
print(score)
|
|
@ -0,0 +1,73 @@
|
|||
from gint import *
|
||||
import math
|
||||
|
||||
palette = b'\x00\x00\xf8\x00\xff\xff'
|
||||
data = b'\x80\x81\x80\x81\x82\x81\x80\x81\x80'
|
||||
img = image(IMAGE_P8_RGB565, color_count=3, width=3, height=3,
|
||||
stride=3, data=data, palette=palette)
|
||||
print(img)
|
||||
|
||||
img_alpha = image_p8_rgb565a(3, 3, data, palette)
|
||||
print(img_alpha)
|
||||
|
||||
# h ∈ [0,360), s ∈ [0,1], l ∈ [0,1]
|
||||
def hsl2rgb(H, S, L):
|
||||
C = (1 - abs(2*L - 1)) * S
|
||||
Hp = H / 60
|
||||
X = C * (1 - abs(Hp % 2 - 1))
|
||||
R, G, B = [(C,X,0), (X,C,0), (0,C,X), (0,X,C), (X,0,C), (C,0,X)][int(Hp)]
|
||||
m = L - C / 2
|
||||
return (R + m, G + m, B + m)
|
||||
|
||||
gradient_data = bytearray(32*32*2)
|
||||
for y in range(32):
|
||||
for x in range(32):
|
||||
i = (32 * y + x) * 2
|
||||
lx, ly = x-15.5, y-15.5
|
||||
radius = (lx*lx + ly*ly) / (16**2)
|
||||
if radius > 1:
|
||||
gradient_data[i] = 0x00
|
||||
gradient_data[i+1] = 0x01
|
||||
continue
|
||||
|
||||
h = math.atan2(-ly, lx) * 180 / math.pi
|
||||
h = h if h >= 0 else h + 360
|
||||
s = radius
|
||||
l = 0.5
|
||||
r, g, b = hsl2rgb(h, s, l)
|
||||
color = C_RGB(int(r*32), int(g*32), int(b*32))
|
||||
gradient_data[i] = color >> 8
|
||||
gradient_data[i+1] = color & 0xff
|
||||
|
||||
gradient = image_rgb565a(32, 32, gradient_data)
|
||||
print(gradient)
|
||||
|
||||
from cg_image_puzzle import *
|
||||
print(puzzle)
|
||||
|
||||
# Take graphics control
|
||||
dupdate()
|
||||
|
||||
h = DWIDTH // 2
|
||||
dclear(C_WHITE)
|
||||
drect(h, 0, DWIDTH-1, DHEIGHT-1, C_RGB(28,28,28))
|
||||
|
||||
dimage(10, 10, img)
|
||||
dimage(15, 10, img)
|
||||
dimage(20, 10, img)
|
||||
dimage(h+10, 10, img_alpha)
|
||||
dimage(h+15, 10, img_alpha)
|
||||
dimage(h+20, 10, img_alpha)
|
||||
dimage(h-16, 20, gradient)
|
||||
dimage(40, 100, puzzle)
|
||||
|
||||
x, y = 110, 100
|
||||
hw = puzzle.width // 2
|
||||
hh = puzzle.height // 2
|
||||
dsubimage(x-1, y-1, puzzle, 0, 0, hw, hh)
|
||||
dsubimage(x+hw+1, y-1, puzzle, hw, 0, hw, hh)
|
||||
dsubimage(x-1, y+hh+1, puzzle, 0, hh, hw, hh)
|
||||
dsubimage(x+hw+1, y+hh+1, puzzle, hw, hh, hw, hh)
|
||||
|
||||
dupdate()
|
||||
getkey()
|
After Width: | Height: | Size: 5.7 KiB |
|
@ -0,0 +1,44 @@
|
|||
from gint import *
|
||||
|
||||
if DWIDTH==128:
|
||||
C_RGB = lambda r, g, b: 0
|
||||
_ = lambda x, y: x
|
||||
else:
|
||||
_ = lambda x, y: y
|
||||
|
||||
dclear(C_WHITE)
|
||||
|
||||
fill1 = _(C_NONE, C_RGB(24, 24, 24))
|
||||
fill2 = _(C_BLACK, C_RGB(24, 24, 24))
|
||||
|
||||
x1 = _(5,20)
|
||||
x2 = _(40,90)
|
||||
x3 = _(64,120)
|
||||
x4 = _(97,220)
|
||||
y1 = _(2,20)
|
||||
y2 = _(19,60)
|
||||
w1 = _(26,60)
|
||||
h1 = _(15,30)
|
||||
|
||||
dellipse(x1, y1, x1+w1, y1+h1, fill1, C_BLACK)
|
||||
dellipse(x1, y2, x1+w1, y2+4, fill1, C_BLACK)
|
||||
dellipse(x1, y2+_(6,10), x1+w1, y2+_(6,10), fill1, C_BLACK)
|
||||
dellipse(x2, y1, x2+4, y1+h1, fill1, C_BLACK)
|
||||
dellipse(x2+10, y1, x2+20, y1+h1, fill1, C_BLACK)
|
||||
dellipse(x3, y1, x3+w1, y1+h1, C_NONE, C_BLACK)
|
||||
dellipse(x4, y1, x4+w1, y1+h1, fill2, C_NONE)
|
||||
|
||||
y3 = _(40,135)
|
||||
y4 = _(55,170)
|
||||
r = _(10,20)
|
||||
x1 += w1 // 2
|
||||
|
||||
dcircle(x1, y3, w1//2, fill1, C_BLACK)
|
||||
dcircle(x1, y4+2, 2, fill1, C_BLACK)
|
||||
dcircle(x1, y4+_(6,10), 0, fill1, C_BLACK)
|
||||
dcircle(x2+r, y3, r, fill1, C_BLACK)
|
||||
dcircle(x3+w1//2, y3, r, C_NONE, C_BLACK)
|
||||
dcircle(x4+w1//2, y3, r, fill2, C_NONE)
|
||||
|
||||
dupdate()
|
||||
getkey()
|
|
@ -0,0 +1,36 @@
|
|||
from casioplot import *
|
||||
|
||||
B=(0,0,0)
|
||||
W=(255,255,255)
|
||||
|
||||
clear_screen()
|
||||
set_pixel(1, 1, B)
|
||||
|
||||
for x in range(10):
|
||||
set_pixel(x+1,3,B)
|
||||
|
||||
for y in range(40):
|
||||
for x in range(10):
|
||||
set_pixel(x+1,y+5,B)
|
||||
|
||||
draw_string(55,1,"Hello,",B,"large")
|
||||
draw_string(55,31,"medium",B,"medium")
|
||||
draw_string(55,51,"world!",B,"small")
|
||||
|
||||
img = b'\x04@"\x00\x0e\xa6W\x00\x0e\xafW\x00\x05\x1f\x89\x00u/J\xc0\xf5F*\xe0'+\
|
||||
b'\xe4\xc92\xe0\x8cP\xa1 \x8c{\xe1 \x8c\xbf\xb1 \x8c\xb1\xb1 \x9c\x950'+\
|
||||
b'\xa0\x9e\xb1\x90\xa0\x8e\x7f\xc3 \xc3\xfb\xfc`\xe0\x1d\xc0\xe0\xbf\x12'+\
|
||||
b'\x1f\xa0_\t\x1f@ \x89 \x80\x1f\x92?\x00'
|
||||
|
||||
for y in range(20):
|
||||
for x in range(27):
|
||||
offset = y * 4 + (x // 8)
|
||||
bit = 0x80 >> (x & 7)
|
||||
if img[offset] & bit:
|
||||
set_pixel(x+20,y+2,B)
|
||||
|
||||
show_screen()
|
||||
|
||||
# TODO: Don't require a wait after casioplot ends
|
||||
import gint
|
||||
gint.getkey()
|
|
@ -0,0 +1,8 @@
|
|||
from gint import *
|
||||
dclear(C_WHITE)
|
||||
for y in range(10):
|
||||
for x in range(10):
|
||||
if (x^y) & 1:
|
||||
dpixel(x, y, C_BLACK)
|
||||
dupdate()
|
||||
getkey()
|
|
@ -0,0 +1,46 @@
|
|||
from gint import *
|
||||
import math
|
||||
|
||||
if DWIDTH==128:
|
||||
C_RGB = lambda r, g, b: 0
|
||||
_ = lambda x, y: x
|
||||
else:
|
||||
_ = lambda x, y: y
|
||||
|
||||
dclear(C_WHITE)
|
||||
|
||||
c1 = _(C_BLACK, C_RGB(24, 24, 24))
|
||||
c2 = _(C_BLACK, C_BLACK)
|
||||
c3 = _(C_NONE, C_RGB(24, 24, 24))
|
||||
|
||||
x1 = _(5,20)
|
||||
x2 = _(40,90)
|
||||
x3 = _(120,360)
|
||||
y1 = _(2,20)
|
||||
y2 = _(19,60)
|
||||
y3 = _(30,135)
|
||||
y4 = _(45,170)
|
||||
y5 = _(50,190)
|
||||
|
||||
xp = _(90,200)
|
||||
yp = _(25,100)
|
||||
rp = _(20,50)
|
||||
|
||||
drect(x1, y1, x2, y2, c1)
|
||||
drect_border(x1, y3, x2, y4, c3, 2, c2)
|
||||
|
||||
dvline(x3, c1)
|
||||
dvline(x3+2, c1)
|
||||
dvline(x3+4, c1)
|
||||
dhline(y5, c2)
|
||||
dhline(y5+2, c2)
|
||||
dhline(y5+4, c2)
|
||||
|
||||
p = [2*math.pi*i/7 for i in range(7)]
|
||||
p = [(int(xp+rp*math.cos(a)), int(yp+rp*math.sin(a))) for a in p]
|
||||
|
||||
for i in range(7):
|
||||
dline(*p[i], *p[(i+2)%7], C_BLACK)
|
||||
|
||||
dupdate()
|
||||
getkey()
|
|
@ -0,0 +1,10 @@
|
|||
import gint
|
||||
|
||||
while True:
|
||||
ev = gint.getkey_opt(gint.GETKEY_DEFAULT, 5000)
|
||||
if ev.type == gint.KEYEV_NONE:
|
||||
print("no press after 5000 ms")
|
||||
else:
|
||||
print(ev)
|
||||
if ev.key == gint.KEY_EXIT and not ev.shift and not ev.alpha:
|
||||
break
|
|
@ -0,0 +1,103 @@
|
|||
from gint import *
|
||||
|
||||
data1 = [
|
||||
[" ", " ", " ", " ", "####"],
|
||||
["### ", " ", " ", " ", "####"],
|
||||
["### ", " # ", " # ", " # ", "####"],
|
||||
["### ", " ", " ", " ", "####"]]
|
||||
data2 = [
|
||||
[" ", " ###", " ###", " ", "####"],
|
||||
[" ###", " ###", " ###", " # #", "####"],
|
||||
[" ###", " ###", " ###", " # #", "####"],
|
||||
[" ", " ###", " ", " # #", "####"]]
|
||||
|
||||
def line(pos1,pos2):
|
||||
x1=int(pos1[0])
|
||||
y1=int(pos1[1])
|
||||
x2=int(pos2[0])
|
||||
y2=int(pos2[1])
|
||||
dline(x1, y1, x2, y2, C_BLACK)
|
||||
|
||||
BLOCK_H=24
|
||||
BLOCK_W=24
|
||||
|
||||
BLOCK_13=BLOCK_H//3
|
||||
BLOCK_23=BLOCK_13*2
|
||||
|
||||
BLOCK_W12=BLOCK_W//2
|
||||
|
||||
BLOCK_H131=BLOCK_13-1
|
||||
BLOCK_W121=BLOCK_W12-1
|
||||
|
||||
block = [
|
||||
[[0,BLOCK_13-1],[BLOCK_W12-1,0]],
|
||||
[[0,BLOCK_13-1],[BLOCK_W12-1,BLOCK_23-1]],
|
||||
[[BLOCK_W12-1,0],[BLOCK_W-1,BLOCK_13-1]],
|
||||
[[BLOCK_W12-1,BLOCK_23-1],[BLOCK_W-1,BLOCK_13-1]],
|
||||
[[0,BLOCK_13-1],[0,BLOCK_23-1]],
|
||||
[[BLOCK_W12-1,BLOCK_23-1],[BLOCK_W12-1,BLOCK_H-1]],
|
||||
[[BLOCK_W-1,BLOCK_13-1],[BLOCK_W-1,BLOCK_23-1]],
|
||||
[[0,BLOCK_23-1],[BLOCK_W12-1,BLOCK_H-1]],
|
||||
[[BLOCK_W12-1,BLOCK_H-1],[BLOCK_W-1,BLOCK_23-1]],
|
||||
]
|
||||
|
||||
def genblock(block):
|
||||
vram=[' ' for i in range(32*BLOCK_H)]
|
||||
for i in block:
|
||||
line(i[0],i[1])
|
||||
for y in range(BLOCK_H):
|
||||
for x in range(BLOCK_W):
|
||||
o=dgetpixel(x,y)
|
||||
if o==C_BLACK: vram[y*BLOCK_W+x]='#'
|
||||
else: vram[y*BLOCK_W+x]=' '
|
||||
for y in range(BLOCK_H):
|
||||
for x in range(BLOCK_W):
|
||||
if vram[y*BLOCK_W+x] == ' ':
|
||||
vram[y*BLOCK_W+x]='t'
|
||||
#print(x,y)
|
||||
else:
|
||||
vram[y*BLOCK_W+x]='#'
|
||||
break
|
||||
for x in range(BLOCK_W-1,-1,-1):
|
||||
if vram[y*BLOCK_W+x] == ' ':
|
||||
vram[y*BLOCK_W+x]='t'
|
||||
#print(x,y)
|
||||
else:
|
||||
vram[y*BLOCK_W+x]='#'
|
||||
break
|
||||
return vram
|
||||
|
||||
def dcube(sx,sy,cube):
|
||||
for y in range(BLOCK_H):
|
||||
for x in range(BLOCK_W):
|
||||
if cube[y*BLOCK_W+x] == ' ': dpixel(sx+x,sy+y,C_WHITE)
|
||||
if cube[y*BLOCK_W+x] == '#': dpixel(sx+x,sy+y,C_BLACK)
|
||||
|
||||
cube=genblock(block)
|
||||
|
||||
def render(data,sx,sy,sz):
|
||||
global cube
|
||||
dx=0
|
||||
dy=0
|
||||
dz=0
|
||||
for z in data:
|
||||
dy=0
|
||||
z.reverse()
|
||||
for y in z:
|
||||
dx=0
|
||||
for t in y:
|
||||
if t == '#':
|
||||
dcube((dx*BLOCK_W121+(dz*(-BLOCK_W121)))+sx,(dx+dz)*BLOCK_H131+(dy*(-BLOCK_H131))+sy,cube)
|
||||
dx+=1
|
||||
dy+=1
|
||||
dz+=1
|
||||
|
||||
dclear(C_WHITE)
|
||||
render(data1,48,32,0)
|
||||
dupdate()
|
||||
getkey()
|
||||
|
||||
dclear(C_WHITE)
|
||||
render(data2,48,32,0)
|
||||
dupdate()
|
||||
getkey()
|
|
@ -0,0 +1,7 @@
|
|||
from matplotl import *
|
||||
|
||||
x = [119.1, 119.3, 119.5, 119.6, 119.9, 120.0, 120.1, 120.3, 120.4]
|
||||
y = [1, 3, 4, 3, 1, 3, 1, 3, 1]
|
||||
|
||||
bar(x, y, 0.08)
|
||||
show()
|
|
@ -0,0 +1,16 @@
|
|||
from gint import *
|
||||
|
||||
dclear(C_WHITE)
|
||||
|
||||
listvert = [0,0,127,0,127,63,0,63]
|
||||
fill = C_RED
|
||||
border = C_BLUE
|
||||
dpoly(listvert, fill, border)
|
||||
|
||||
listvert2 = [100, 50, 200, 50, 225, 75, 200, 100, 100, 100, 75, 75]
|
||||
listvert3 = [100, 100, 200, 100, 225, 125, 200, 150, 100, 150, 75, 125]
|
||||
dpoly(listvert2, C_NONE, C_BLACK)
|
||||
dpoly(listvert3, C_GREEN, C_NONE)
|
||||
|
||||
dupdate()
|
||||
getkey()
|
|
@ -0,0 +1,23 @@
|
|||
import turtle
|
||||
from math import exp
|
||||
|
||||
def try_colormode(m):
|
||||
try: turtle.colormode(m)
|
||||
except: pass
|
||||
def try_pencolor(c):
|
||||
try: turtle.pencolor(c)
|
||||
except: pass
|
||||
try: turtle.color(c)
|
||||
except: pass
|
||||
|
||||
try_colormode(1)
|
||||
turtle.penup()
|
||||
turtle.goto(0, -20)
|
||||
turtle.pendown()
|
||||
for i in range(1,37):
|
||||
red=(exp(-0.5 * ((i-6)/12)**2))
|
||||
green=(exp(-0.5 * ((i-18)/12)**2))
|
||||
blue=(exp(-0.5 * ((i-30)/12)**2))
|
||||
try_pencolor([red,green,blue])
|
||||
turtle.circle(50-i)
|
||||
turtle.right(10)
|
|
@ -0,0 +1,150 @@
|
|||
#Flappy Bird Python
|
||||
#par Xavier Andreani (tiplanet.org) et
|
||||
#Sebastien Michelland (planet-casio.com)
|
||||
#pour Graph 35+E II, fx-9750GIII, fx-9860GIII
|
||||
#--------------------
|
||||
from casioplot import *
|
||||
from random import randint
|
||||
from gint import *
|
||||
from micropython import *
|
||||
from gc import *
|
||||
opt_level(3)
|
||||
#CONFIG GRAPHIQ CASIO
|
||||
L_FENETRE, H_FENETRE = 128, 64 #dimensions de la zone graphique affichable
|
||||
LNUMH_POLICE = {"small":(4,5), "medium":(4,5), "large": (6,7)}
|
||||
POLICE = "small" #taille de police (small, medium ou large)
|
||||
LNUM_POLICE, H_POLICE = LNUMH_POLICE[POLICE][:2] #dimensions des caracteres de la police (largeur numeriques + hauteur)
|
||||
#CONFIG GRAPHIQUE JEU
|
||||
L_TUYAU, HMIN_TUYAU = 16, 9 #largeur + hauteur minimale des tuyaux
|
||||
H_SOL = H_POLICE + 2 #hauteur du sol
|
||||
H_FOND = H_FENETRE - H_SOL #hauteur du fond
|
||||
D_FBIRD, L_FBIRD, H_FBIRD = 32, 10, 7 #position initiale + largeur + hauteur de Flappy Bird
|
||||
INTH_TUYAUX, INTVMIN_TUYAUX = 64, 16 #espacement horizontal + vertical minimal entre les tuyaux
|
||||
MAX_TUYAUX = 3 #nombre de tuyaux maximal en RAM
|
||||
#EXTENSION CASIOPLOT
|
||||
#FONCTIONS GRAPHIQ JEU
|
||||
COULEUR_BORD, COULEUR_FOND, COULEUR_SOL, COULEUR_TUYAU = C_BLACK, C_WHITE, C_WHITE, C_BLACK
|
||||
PALETTE = (C_WHITE, C_BLACK)
|
||||
BIRD_IMG = (
|
||||
" #### ",
|
||||
" ## # # ",
|
||||
"# # # # ",
|
||||
"# # #### ",
|
||||
" ### # #",
|
||||
" # ### ",
|
||||
" ### ")
|
||||
# traduction des caracteres en couleurs
|
||||
BIRD = [[PALETTE[c == "#"] for c in line] for line in BIRD_IMG]
|
||||
margin = 0 #Nombre de tuyaux supprimes
|
||||
ntuyaux = 0 #Nombre de tuyaux
|
||||
DEBUG = False
|
||||
def y_altitude(alt):
|
||||
"""retourne la position verticale d'affichage d'un objet situe a l'altitude alt"""
|
||||
return H_FOND - alt
|
||||
def draw_tuyaux(x, hinf, hsup):
|
||||
"""affiche une paire de tuyaux de hauteurs hinf (inferieur) et hsup (superieur) avec x comme limite gauche"""
|
||||
yinf = y_altitude(hinf)
|
||||
drect_border(x, hsup - 6, x + L_TUYAU, hsup,
|
||||
C_WHITE, 1, COULEUR_TUYAU); drect_border(x + 3, 0, x + L_TUYAU - 3, hsup - 6, C_WHITE, 1, COULEUR_TUYAU)
|
||||
drect_border(x, yinf, x + L_TUYAU, yinf + 6,
|
||||
C_WHITE, 1, COULEUR_TUYAU); drect_border(x + 3, yinf + 6, x + L_TUYAU - 3, yinf + hinf - 1, C_WHITE, 1, COULEUR_TUYAU)
|
||||
def draw_fbird(x, y, x_ancien, y_ancien):
|
||||
"""dessine Flappy Bird dans un rectangle de L_FBIRD*H_FBIRD pixels avec comme coin superieur gauche (x;y)"""
|
||||
y = round(y)
|
||||
for ligne in range(H_FBIRD):
|
||||
for col in range(L_FBIRD): dpixel(x + col, y + ligne, BIRD[ligne][col])
|
||||
def draw_sol():
|
||||
"""affiche le sol et dedans les informations"""
|
||||
dhline(H_FENETRE - H_POLICE - 2, COULEUR_BORD)
|
||||
info = vx_fenetre == 0 and "[AC]: Demarrer" or vx_fbird!=0 and "[AC]: Battre des ailes" or "[AC]: Quitter"
|
||||
draw_string(1, H_FENETRE - H_POLICE, info, (0, 0, 0), POLICE)
|
||||
def draw_score():
|
||||
"""affiche le score dans le coin inferieur droit"""
|
||||
ch_score = str(score)
|
||||
draw_string(L_FENETRE - LNUM_POLICE * len(ch_score), H_FENETRE - H_POLICE, ch_score, (0, 0, 0), POLICE)
|
||||
def draw_jeu():
|
||||
"""initialise l'affichage en dessinant l'ensemble des elements graphiques"""
|
||||
dclear(C_WHITE)
|
||||
draw_fbird(d_fbird - d_fenetre, y_altitude(alt_fbird), d_fbird_ancien - d_fenetre, y_altitude(alt_fbird_ancien))
|
||||
for k in range(0, len(d_tuyaux)):
|
||||
d_tuyau = d_tuyaux[k]
|
||||
if d_tuyau+L_TUYAU >= d_fenetre and d_tuyau < d_fenetre+L_FENETRE:
|
||||
draw_tuyaux(d_tuyau - d_fenetre, hinf_tuyaux[k], hsup_tuyaux[k])
|
||||
draw_sol(); draw_score()
|
||||
#AUTRES FONCTIONS JEU
|
||||
def ajoute_tuyau():
|
||||
"""ajoute une paire de tuyaux"""
|
||||
global d_tuyaux, hinf_tuyaux, hsup_tuyaux, margin, ntuyaux
|
||||
d_tuyaux.append(d_tuyaux[-1] + INTH_TUYAUX)
|
||||
hinf_tuyau = randint(HMIN_TUYAU, H_FOND - INTVMIN_TUYAUX - HMIN_TUYAU)
|
||||
hsup_tuyau = randint(HMIN_TUYAU, H_FOND - hinf_tuyau - INTVMIN_TUYAUX)
|
||||
hinf_tuyaux.append(hinf_tuyau); hsup_tuyaux.append(hsup_tuyau)
|
||||
ntuyaux += 1
|
||||
if ntuyaux>MAX_TUYAUX:
|
||||
del d_tuyaux[0]; del hinf_tuyaux[0]; del hsup_tuyaux[0]
|
||||
ntuyaux -= 1
|
||||
margin += 1
|
||||
|
||||
def simulation():
|
||||
"""met a jour l'etat du jeu"""
|
||||
global d_fenetre, d_fbird, d_fbird_ancien, alt_fbird, alt_fbird_ancien, vx_fbird, vy_fbird, score, margin
|
||||
if d_fenetre + L_FENETRE >= d_tuyaux[-1] + INTH_TUYAUX: ajoute_tuyau()
|
||||
if d_tuyaux[score - margin] + L_TUYAU<d_fbird: score += 1 # le score correspond a l'index du tuyau a tester
|
||||
if vx_fbird > 0 and collision_fbird():
|
||||
vx_fbird = 0
|
||||
if vy_fbird>0: vy_fbird = 0
|
||||
draw_sol()
|
||||
if vx_fenetre != 0 and vx_fbird != 0:
|
||||
d_fenetre -= vx_fenetre
|
||||
d_fbird_ancien, alt_fbird_ancien = d_fbird, alt_fbird
|
||||
d_fbird += vx_fbird
|
||||
alt_fbird = max(H_FBIRD, alt_fbird + vy_fbird)
|
||||
vy_fbird += dy_gravite
|
||||
def isect_rect(x1, y1, w1, h1, x2, y2, w2, h2):
|
||||
"""teste si il y a une intersection entre les rectangles
|
||||
de largeur w1 hauteur h1 au coin superieur gauche (x1;y1)
|
||||
et largeur w2 hauteur h2 au coin superieur gauche (x2;y2)
|
||||
"""
|
||||
return max(x1, x2) <= min(x1 + w1, x2 + w2) and max(y1, y2) <= min(y1 + h1, y2 + h2)
|
||||
def collision_fbird():
|
||||
"""teste si il y a collision entre Flappy Bird et les actuels tuyaux inferieur ou superieur"""
|
||||
d_tuyau, hinf_tuyau, hsup_tuyau = d_tuyaux[score - margin], hinf_tuyaux[score - margin], hsup_tuyaux[score - margin]
|
||||
y_fbird = y_altitude(alt_fbird)
|
||||
isect_inf = isect_rect(d_tuyau, y_altitude(hinf_tuyau), L_TUYAU, hinf_tuyau, d_fbird, y_fbird, L_FBIRD, H_FBIRD)
|
||||
isect_sup = isect_rect(d_tuyau, y_fbird, L_TUYAU, hsup_tuyau - y_fbird, d_fbird, y_fbird, L_FBIRD, H_FBIRD)
|
||||
return isect_inf or isect_sup
|
||||
def action():
|
||||
"""effectue l'action correspondant a la touche pressee"""
|
||||
try:
|
||||
global vx_fenetre, vy_fbird
|
||||
if vx_fenetre == 0:
|
||||
vx_fenetre = -1
|
||||
draw_sol()
|
||||
elif vx_fbird != 0: vy_fbird = 1.25
|
||||
else:
|
||||
print("score:\n", score)
|
||||
if DEBUG: print(mem_free())
|
||||
raise SystemExit
|
||||
except KeyboardInterrupt: action()
|
||||
#ETAT INITIAL JEU
|
||||
d_tuyaux = [L_FENETRE * 3 // 4] #emplacements horizontaux des tuyaux
|
||||
hinf_tuyaux, hsup_tuyaux = [HMIN_TUYAU + 5], [HMIN_TUYAU + 5] #hauteurs des tuyaux
|
||||
score = 0 #nombre de tuyaux franchis
|
||||
d_fbird, alt_fbird = D_FBIRD, H_FOND * 3 // 4 #distance + altitude de Flappy Bird
|
||||
d_fbird_ancien, alt_fbird_ancien = d_fbird, alt_fbird # anciennes distance + altitude de Flappy Bird
|
||||
vx_fbird, vy_fbird = 1, 0 # vitesses horizontale + verticale de Flappy Bird
|
||||
dy_gravite = -0.1 # acceleration verticale de la pesanteur
|
||||
vx_fenetre, d_fenetre = 0, 0 # vitesse scrolling horizontale + position de la fenetre
|
||||
#LANCEMENT JEU
|
||||
ajoute_tuyau()
|
||||
def game():
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
draw_jeu(); dupdate()
|
||||
simulation()
|
||||
except KeyboardInterrupt: action()
|
||||
except KeyboardInterrupt:
|
||||
game()
|
||||
if DEBUG: print(mem_free())
|
||||
game()
|
|
@ -0,0 +1,44 @@
|
|||
from gint import *
|
||||
|
||||
img = image(IMAGE_MONO, width=3, height=3, data=b'\xa0\x00\x00\x00\x50\x00\x00\x00\xa0\x00\x00\x00')
|
||||
|
||||
print(img)
|
||||
print(img.format, img.width, img.height)
|
||||
print(img.data)
|
||||
|
||||
segments = image(IMAGE_MONO, 79, 12, bytearray(b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00'))
|
||||
print(segments)
|
||||
|
||||
# ..xx x.. | ..xx x..
|
||||
# .x.. .x. | .xxx xx.
|
||||
# x..x ..x | xxxx xxx
|
||||
# x.xx x.x | xxxx xxx
|
||||
# x..x ..x | xxxx xxx
|
||||
# .x.. .x. | .xxx xx.
|
||||
# ..xx x.. | ..xx x..
|
||||
alpha = image(IMAGE_MONO_ALPHA, 7, 7, b'\x38\x00\x00\x00\x38\x00\x00\x00\x7c\x00\x00\x00\x44\x00\x00\x00\xfe\x00\x00\x00\x92\x00\x00\x00\xfe\x00\x00\x00\xba\x00\x00\x00\xfe\x00\x00\x00\x92\x00\x00\x00\x7c\x00\x00\x00\x44\x00\x00\x00\x38\x00\x00\x00\x38\x00\x00\x00')
|
||||
|
||||
# Take graphics control again after the print()
|
||||
dupdate()
|
||||
dclear(C_WHITE)
|
||||
drect(63, 0, 127, 63, C_BLACK)
|
||||
dimage(10, 5, img)
|
||||
dimage(10, 15, segments)
|
||||
|
||||
def digit(x, y, num):
|
||||
dsubimage(x, y, segments, 8*num, 0, 7, segments.height)
|
||||
|
||||
digit(15+0*8, 45, 4)
|
||||
digit(15+1*8, 45, 2)
|
||||
digit(15+2*8, 45, 7)
|
||||
digit(15+3*8, 45, 3)
|
||||
|
||||
d = segments.data
|
||||
for i in range(len(d) / 2):
|
||||
d[i] = ~d[i]
|
||||
|
||||
dimage(10, 30, segments)
|
||||
dimage(60, 5, alpha)
|
||||
|
||||
dupdate()
|
||||
getkey()
|
After Width: | Height: | Size: 660 B |
|
@ -0,0 +1,223 @@
|
|||
# PacMan par Kevin FEDYNA
|
||||
# https://nsi.xyz/numapps/pac-man-en-python-numworks/
|
||||
|
||||
from kandinsky import fill_rect, draw_string
|
||||
from ion import keydown
|
||||
from math import sqrt
|
||||
from random import randint
|
||||
from time import monotonic
|
||||
|
||||
try:
|
||||
from kandinsky import get_keys
|
||||
color = (192, 53, 53)
|
||||
except:
|
||||
color = (255, 183, 52)
|
||||
|
||||
terrain = (262143,131841,187245,187245,131073,186285,135969,252783,249903,251823,1152,251823,249903,251823,131841,187245,147465,219051,135969,195453,131073,262143)
|
||||
bits = 18
|
||||
width = 320
|
||||
height = 222
|
||||
colors = ((0, 0, 0), (32, 48, 248), (248, 224, 8), tuple(color))
|
||||
ghost_color = ((255, 184, 255), (255, 0,0), (255, 184, 82), (0, 255, 255))
|
||||
pacgommes = [0,130302,9360,74898,131070,75858,126174,8208,8208,8208,8208,8208,8208,8208,130302,74898,49140,43092,126174,66690,131070,0]
|
||||
superpacgommes = [0,0,65538,0,0,0,0,0,0,0,0,0,0,0,0,0,65538,0,0,0,0,0,0]
|
||||
frightened = 0
|
||||
lives = 2
|
||||
won = 0
|
||||
lvl = 0
|
||||
score = 0
|
||||
chained = 0
|
||||
|
||||
|
||||
class Entity:
|
||||
def __init__(self, x, y, clr, d=0):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.d = d
|
||||
self.nd = d
|
||||
self.f = 0
|
||||
self.out = 0
|
||||
self.color = clr
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,self.color)
|
||||
def espace(self,dx=-1,dy=-1):
|
||||
if dx == dy:
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[self.nd]
|
||||
return not terrain[int(self.y + 5.5*dy)]>>(bits-1-int(self.x + 5.5*dx)) & 1 and ((dx != 0 and self.y%1 == 0.5) or (dy != 0 and self.x%1== 0.5))
|
||||
def move(self):
|
||||
global frightened, ghosts, score, chained, lives, total, won
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[self.d]
|
||||
if self.espace(dx,dy):
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,colors[0])
|
||||
self.x = (round(self.x + dx, 1) - 0.5) % 16.5 + 0.5
|
||||
self.y = round(self.y + dy, 1)
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,self.color)
|
||||
if self.color == colors[2]:
|
||||
if pacgommes[int(self.y)] >> (bits - 1 - int(self.x)) & 1:
|
||||
pacgommes[int(self.y)] -= 1 << (bits - 1 - int(self.x))
|
||||
score += 10
|
||||
if superpacgommes[int(self.y)] >> (bits - 1 - int(self.x)) & 1:
|
||||
superpacgommes[int(self.y)] -= 1 << (bits - 1 - int(self.x))
|
||||
score += 50
|
||||
chained = 0
|
||||
frightened = monotonic()
|
||||
for g in ghosts:
|
||||
if g.out:
|
||||
g.color = colors[1]
|
||||
g.d = (3, 2, 1, 0)[g.d]
|
||||
g.f = 1
|
||||
for g in range(4):
|
||||
if sqrt((self.x-ghosts[g].x)**2+(self.y-ghosts[g].y)**2) < 0.6:
|
||||
if ghosts[g].f:
|
||||
chained += 1
|
||||
total += 1
|
||||
score += (1 << chained)*100
|
||||
ghosts[g].f = 0
|
||||
ghosts[g].color = ghost_color[g]
|
||||
ghosts[g].x = 9
|
||||
ghosts[g].y = 8.5
|
||||
if total == 16:
|
||||
score += 12000
|
||||
else:
|
||||
for gp in range(4):
|
||||
ghosts[gp].f = 0
|
||||
ghosts[gp].color = ghost_color[gp]
|
||||
ghosts[gp].x = 9
|
||||
ghosts[gp].y = 10.5
|
||||
ghosts[gp].out = 0
|
||||
self.x = 9
|
||||
self.y = 16.5
|
||||
self.d, self.nd = 0, 0
|
||||
lives -= 1
|
||||
return render()
|
||||
if not won and score > 10000:
|
||||
lives += 1
|
||||
won = 1
|
||||
px, py = int(self.x - 5.5*dx), int(self.y - 5.5*dy)
|
||||
if pacgommes[py]>>(bits-1-px) & 1:
|
||||
fill_rect(px*10+144,py*10+5,2,2,(250, 207, 173))
|
||||
if superpacgommes[py]>>(bits-1-px) & 1:
|
||||
fill_rect(px*10+143,py*10+4,4,4,(250, 207, 173))
|
||||
def ia(self,x,y):
|
||||
if self.f:
|
||||
while True:
|
||||
d = randint(0,3)
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[d]
|
||||
if d != (3,2,1,0)[self.d] and self.espace(dx,dy):
|
||||
self.d = d
|
||||
break
|
||||
else:
|
||||
distances = [9999 for _ in range(4)]
|
||||
for i in range(4):
|
||||
if i != (3,2,1,0)[self.d]:
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[i]
|
||||
if self.espace(dx,dy):
|
||||
distances[i] = sqrt((self.y + dy - y)**2 + (self.x + dx - x)**2)
|
||||
self.d = distances.index(min(distances))
|
||||
|
||||
def prebuild():
|
||||
fill_rect(0,0,width,height,colors[0])
|
||||
fill_rect(138, 0, 2, height, colors[3])
|
||||
draw_string("PAC-MAN", 35, 10, colors[3], colors[0])
|
||||
draw_string("nsi.xyz/pacman", 0, 204,colors[0], colors[3])
|
||||
draw_string("Score :", 35, 40, (255,)*3, colors[0])
|
||||
draw_string("Niveau :", 30, 90, (255,)*3, colors[0])
|
||||
|
||||
def render():
|
||||
global terrain, pacgommes, superpacgommes, lives, arrivee
|
||||
if lives == -1:
|
||||
return 42
|
||||
draw_string(str(lvl),70-5*len(str(lvl)),110,(255,)*3,colors[0])
|
||||
fill_rect(0,150,138,20,colors[0])
|
||||
for i in range(lives):
|
||||
fill_rect(60-(lives-1)*20+i*40,150,20,20,colors[2])
|
||||
for l in range(len(terrain)):
|
||||
for c in range(bits):
|
||||
fill_rect(c*10+140,l*10+1,10,10,colors[0])
|
||||
if pacgommes[l]>>(bits-1-c) & 1:
|
||||
fill_rect(c*10+144,l*10+5,2,2,(250, 207, 173))
|
||||
if superpacgommes[l]>>(bits-1-c) & 1:
|
||||
fill_rect(c*10+143,l*10+4,4,4,(250, 207, 173))
|
||||
if terrain[l]>>(bits-1-c) & 1:
|
||||
for d in ((1,0),(0,1),(-1,0),(0,-1)):
|
||||
if 0 <= l + d[0] <= len(terrain) - 1 and 0 <= c + d[1] <= bits - 1 and not terrain[l + d[0]]>>(bits-1-(c+d[1])) & 1:
|
||||
fill_rect(c*10+140+9*(d[1]==1),l*10+1+9*(d[0]==1),1+9*(d[1]==0),1+9*(d[0]==0),colors[1])
|
||||
arrivee = monotonic()
|
||||
|
||||
def engine():
|
||||
global frightened, ghosts, pacgommes, superpacgommes, lvl, arrivee, total
|
||||
while True:
|
||||
pacgommes = [0,130302,9360,74898,131070,75858,126174,8208,8208,8208,8208,8208,8208,8208,130302,74898,49140,43092,126174,66690,131070,0]
|
||||
superpacgommes = [0,0,65538,0,0,0,0,0,0,0,0,0,0,0,0,0,65538,0,0,0,0,0,0]
|
||||
lvl += 1
|
||||
total = 0
|
||||
render()
|
||||
pacman = Entity(9, 16.5, colors[2])
|
||||
ghosts = [Entity(9, 10.5, ghost_color[i]) for i in range(4)]
|
||||
while sum(pacgommes) + sum(superpacgommes):
|
||||
depart = monotonic()
|
||||
for i in range(4):
|
||||
if keydown(i):
|
||||
if i == (3,2,1,0)[pacman.d]:
|
||||
pacman.d = i
|
||||
pacman.nd = i
|
||||
while monotonic() - depart < 0.01:
|
||||
if pacman.espace():
|
||||
pacman.d = pacman.nd
|
||||
if pacman.move() == 42:
|
||||
draw_string("GAME OVER",185,100,colors[3],colors[0])
|
||||
return 69
|
||||
|
||||
draw_string(str(score),70-5*len(str(score)),60,(255,)*3,colors[0])
|
||||
|
||||
""" Fantomes """
|
||||
|
||||
if frightened:
|
||||
if monotonic() - frightened > 6.5:
|
||||
for g in ghosts:
|
||||
if g.f:
|
||||
g.color = (255,)*3
|
||||
if monotonic() - frightened > 8.5:
|
||||
frightened = 0
|
||||
for g in range(4):
|
||||
ghosts[g].color = ghost_color[g]
|
||||
ghosts[g].f = 0
|
||||
|
||||
if arrivee:
|
||||
if monotonic() - arrivee > 0 and not ghosts[1].out:
|
||||
ghosts[1].out = 1
|
||||
ghosts[1].y = 8.5
|
||||
if monotonic() - arrivee > 2.5 and not ghosts[0].out:
|
||||
ghosts[0].out = 1
|
||||
ghosts[0].y = 8.5
|
||||
if monotonic() - arrivee > 5 and not ghosts[3].out:
|
||||
ghosts[3].out = 1
|
||||
ghosts[3].y = 8.5
|
||||
if monotonic() - arrivee > 7.5 and not ghosts[2].out:
|
||||
ghosts[2].out = 1
|
||||
ghosts[2].y = 8.5
|
||||
fill_rect(220,101,20,10,colors[0])
|
||||
arrivee = 0
|
||||
|
||||
pdx, pdy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[pacman.d]
|
||||
|
||||
# Pinky
|
||||
ghosts[0].ia(pacman.x + 20 * pdx, pacman.y + 20 * pdy)
|
||||
ghosts[0].move()
|
||||
|
||||
# Inky
|
||||
ghosts[3].ia(max(min(ghosts[1].x + 2*(pacman.x + 20 * pdx - ghosts[1].x), 16.5), 1.5), max(min(ghosts[1].y +2*(pacman.y + 20 * pdy - ghosts[1].y), 21.5), 1.5))
|
||||
ghosts[3].move()
|
||||
|
||||
# Blinky
|
||||
ghosts[1].ia(pacman.x, pacman.y)
|
||||
ghosts[1].move()
|
||||
|
||||
# Clyde
|
||||
if sqrt((ghosts[2].x - pacman.x)**2 + (ghosts[2].y - pacman.y)**2) > 4:
|
||||
ghosts[2].ia(pacman.x, pacman.y)
|
||||
else:
|
||||
ghosts[2].ia(1.5, 20.5)
|
||||
ghosts[2].move()
|
||||
|
||||
prebuild()
|
||||
engine()
|
|
@ -0,0 +1,303 @@
|
|||
# Snake from Golem64
|
||||
# https://my.numworks.com/python/golem64/snake
|
||||
|
||||
#Version 1.7 STABLE
|
||||
#Tip: You should try to press
|
||||
#some keys in the menu...
|
||||
from random import *
|
||||
from kandinsky import *
|
||||
from ion import *
|
||||
from time import *
|
||||
#from pomme import *
|
||||
def oscolor():
|
||||
try:
|
||||
get_keys()
|
||||
except:
|
||||
return 'orange'
|
||||
else:
|
||||
return 'red'
|
||||
def lastPos(i,x,y):
|
||||
if i[-1]==3:
|
||||
pos=[x-10,y]
|
||||
elif i[-1]==2:
|
||||
pos=[x,y-10]
|
||||
elif i[-1]==0:
|
||||
pos=[x+10,y]
|
||||
elif i[-1]==1:
|
||||
pos=[x,y+10]
|
||||
pos[0],pos[1]=checkTeleport(pos[0],pos[1])
|
||||
return pos
|
||||
def newApple(appleC,bgC):
|
||||
applex=randint(0,31)*10+4
|
||||
appley=randint(0,21)*10+5
|
||||
while get_pixel(applex,appley)!=bgC:
|
||||
applex=randint(0,31)*10+4
|
||||
appley=randint(0,21)*10+5
|
||||
fill_rect(applex-4,appley-4,10,10,appleC)
|
||||
return applex,appley
|
||||
def checkTeleport(x,y):
|
||||
if x<4:
|
||||
x=314
|
||||
if x>314:
|
||||
x=4
|
||||
if y<5:
|
||||
y=215
|
||||
if y>215:
|
||||
y=5
|
||||
return x,y
|
||||
def getMove(u):
|
||||
for k in range(4):
|
||||
if keydown(k)==True and u+k!=3: return k
|
||||
return u
|
||||
def clearDraw(): fill_rect(0,0,320,222,(255,255,255))
|
||||
def clearHome(): print("\n \n \n \n \n \n \n \n \n \n \n \n \n ")
|
||||
def redraw():
|
||||
draw_string("(DELETE to exit)",0,0)
|
||||
printLetter([1,1,1,1,0,0,1,1,1,0,0,1,1,1,1],70,80,10,(0,204,0))
|
||||
fill_rect(95,80,2,4,(0,0,0))
|
||||
fill_rect(95,86,2,4,(0,0,0))
|
||||
fill_rect(100,84,4,2,(255,0,0))
|
||||
fill_rect(104,82,2,2,(255,0,0))
|
||||
fill_rect(104,86,2,2,(255,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,0,1,1,0,1,1,0,1],110,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,1,1,1,0,1,1,0,1],150,80,10,(0,0,0))
|
||||
printLetter([1,0,1,1,0,1,1,1,0,1,0,1,1,0,1],190,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,0,1,1,1,1,0,0,1,1,1],230,80,10,(0,0,0))
|
||||
def printLetter(letter,x,y,size,color):
|
||||
for yi in range(5):
|
||||
for xi in range(3):
|
||||
if letter[yi*3+xi]==1:
|
||||
fill_rect(x+(xi*size),y+(yi*size),size,size,color)
|
||||
def menu():
|
||||
clearDraw()
|
||||
printLetter([1,1,1,1,0,1,1,0,1,1,0,1,1,0,1],110,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,1,1,1,0,1,1,0,1],150,80,10,(0,0,0))
|
||||
printLetter([1,0,1,1,0,1,1,1,0,1,0,1,1,0,1],190,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,0,1,1,1,1,0,0,1,1,1],230,80,10,(0,0,0))
|
||||
anim=[1,1,1,1,1,1,1,1,1,4,4,3,3,4,4,1,1]
|
||||
ax=0
|
||||
ay=120
|
||||
aendx=-110
|
||||
aendy=120
|
||||
u=1
|
||||
aback=0
|
||||
for i in range(len(anim)):
|
||||
ax=ax+((anim[i]==1)-(anim[i]==3))*10
|
||||
ay=ay+((anim[i]==2)-(anim[i]==4))*10
|
||||
if aendx<0:
|
||||
aendx=aendx+10
|
||||
else:
|
||||
aendx=aendx+((anim[i-11]==1)-(anim[i-11]==3))*10
|
||||
aendy=aendy+((anim[i-11]==2)-(anim[i-11]==4))*10
|
||||
fill_rect(aendx,aendy,10,10,(255,255,255))
|
||||
fill_rect(ax,ay,10,10,(0,204,0))
|
||||
# aback=lastPos(anim,ax,ay)
|
||||
# if u==26 or u==24:
|
||||
# fill_rect(ax-1,ay-1,3,1,(0,0,0))
|
||||
# fill_rect(ax-1,ay+1,3,1,(0,0,0))
|
||||
# fill_rect(aback[0],aback[1],10,10,(0,204,0))
|
||||
# elif u==34 or u==25:
|
||||
# fill_rect(ax-1,ay-1,1,3,(0,0,0))
|
||||
# fill_rect(ax+1,ay-1,1,3,(0,0,0))
|
||||
# fill_rect(aback[0]-2,aback[1]-2,5,5,(0,204,0))
|
||||
sleep(0.05)
|
||||
fill_rect(ax+5,ay,2,4,(0,0,0))
|
||||
fill_rect(ax+5,ay+6,2,4,(0,0,0))
|
||||
fill_rect(ax+10,ay+4,4,2,(255,0,0))
|
||||
fill_rect(ax+14,ay+2,2,2,(255,0,0))
|
||||
fill_rect(ax+14,ay+6,2,2,(255,0,0))
|
||||
draw_string("(DELETE to exit)",0,0)
|
||||
draw_string("> Play <",125,140,oscolor())
|
||||
draw_string(" Options ",110,165)
|
||||
darkMode=0
|
||||
Speed=0.05
|
||||
power=5
|
||||
score=1
|
||||
exit=0
|
||||
sel=1
|
||||
while keydown(KEY_OK)!=True and exit==0:
|
||||
if keydown(KEY_DOWN) and sel==1:
|
||||
draw_string(" Play ",125,140)
|
||||
draw_string("> Options <",110,165,oscolor())
|
||||
sel=2
|
||||
elif keydown(KEY_UP) and sel==2:
|
||||
draw_string("> Play <",125,140,oscolor())
|
||||
draw_string(" Options ",110,165)
|
||||
sel=1
|
||||
if keydown(KEY_LEFTPARENTHESIS) and keydown(KEY_RIGHTPARENTHESIS):
|
||||
draw_string("Dark mode enabled !",80,195)
|
||||
darkMode=1
|
||||
if keydown(KEY_BACKSPACE):
|
||||
exit=1
|
||||
sleep(0.1)
|
||||
if sel==2 and exit!=1:
|
||||
fill_rect(0,130,300,60,(255,255,255))
|
||||
Speed=0.05
|
||||
power=5
|
||||
score=1
|
||||
draw_string("Speed:"+str(Speed),50,140,oscolor(),'white')
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
sel=1
|
||||
sleep(0.2)
|
||||
while keydown(KEY_OK)!=True or sel!=4:
|
||||
if keydown(KEY_RIGHT):
|
||||
sel=sel+1
|
||||
elif keydown(KEY_DOWN):
|
||||
sel=sel+2
|
||||
elif keydown(KEY_LEFT):
|
||||
sel=sel-1
|
||||
elif keydown(KEY_UP):
|
||||
sel=sel-2
|
||||
if sel<0:
|
||||
sel=0
|
||||
if sel>4:
|
||||
sel=4
|
||||
if sel==1:
|
||||
draw_string("Speed:"+str(Speed),50,140,oscolor(),'white')
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
Speed=input("Speed:")
|
||||
redraw()
|
||||
elif sel==2:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140,oscolor(),'white')
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
power=int(input("Power:+"))
|
||||
redraw()
|
||||
elif sel==3:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170,oscolor(),'white')
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
score=int(input("Score:"))
|
||||
redraw()
|
||||
elif sel==4:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170,oscolor(),'white')
|
||||
if (keydown(KEY_LEFTPARENTHESIS) and keydown(KEY_RIGHTPARENTHESIS)) or darkMode==1:
|
||||
draw_string("Dark mode enabled !",80,195)
|
||||
darkMode=1
|
||||
if keydown(KEY_BACKSPACE):
|
||||
exit=1
|
||||
break
|
||||
sleep(0.1)
|
||||
if exit!=1:
|
||||
if darkMode==1:
|
||||
launch(1,Speed,power,score)
|
||||
elif darkMode==0:
|
||||
launch(0,Speed,power,score)
|
||||
elif exit==1:
|
||||
clearDraw()
|
||||
return
|
||||
def launch(darkmode=0,speed=0.05,applePower=5,appleScore=1):
|
||||
bgC=(248,252,248)
|
||||
borderC=(0,0,0)
|
||||
snakeC=(0,204,0)
|
||||
appleC=(248,0,0)
|
||||
if darkmode==1:
|
||||
bgC=(0,0,0)
|
||||
borderC=(0,0,204)
|
||||
fill_rect(0,0,320,222,bgC)
|
||||
# fill_rect(315,0,5,222,borderC)
|
||||
# fill_rect(0,0,5,222,borderC)
|
||||
# fill_rect(0,0,320,1,(197,52,49))
|
||||
fill_rect(0,221,320,1,(0,0,0))
|
||||
try:
|
||||
get_keys()
|
||||
except:
|
||||
fill_rect(0,0,320,1,(255,181,49))
|
||||
else:
|
||||
fill_rect(0,0,320,1,(197,52,49))
|
||||
snake=[3,3,3,3,3]
|
||||
x=154
|
||||
y=115
|
||||
endx=104
|
||||
endy=115
|
||||
u,v=3,3
|
||||
length=5
|
||||
applex,appley=newApple(appleC,bgC)
|
||||
score,touched=0,0
|
||||
while touched!=borderC and touched!=snakeC:
|
||||
if keydown(0) or keydown(1) or keydown(2) or keydown(3):
|
||||
u=getMove(u)
|
||||
if keydown(KEY_BACKSPACE):
|
||||
while keydown(KEY_BACKSPACE):
|
||||
sleep(0.1)
|
||||
while keydown(KEY_BACKSPACE)!=True:
|
||||
sleep(0.1)
|
||||
while keydown(KEY_BACKSPACE):
|
||||
sleep(0.1)
|
||||
snake.append(u)
|
||||
if x==applex and y==appley:
|
||||
length=length+float(applePower)
|
||||
applex,appley=newApple(appleC,bgC)
|
||||
score=score+int(appleScore)
|
||||
x=x+((u==3)-(u==0))*10
|
||||
y=y+((u==2)-(u==1))*10
|
||||
x,y=checkTeleport(x,y)
|
||||
if length:
|
||||
length=length-1
|
||||
else:
|
||||
snake.remove(snake[0])
|
||||
endx=endx+((v==3)-(v==0))*10
|
||||
endy=endy+((v==2)-(v==1))*10
|
||||
endx,endy=checkTeleport(endx,endy)
|
||||
v=snake[0]
|
||||
fill_rect(endx-4,endy-4,10,10,bgC)
|
||||
touched=get_pixel(x,y)
|
||||
if x<0 or x>320 or y<0 or y>220:
|
||||
touched=borderC
|
||||
if touched!=appleC and touched!=bgC:
|
||||
touched=borderC
|
||||
fill_rect(x-4,y-4,10,10,snakeC)
|
||||
back=lastPos(snake,x,y)
|
||||
if u==3 or u==0:
|
||||
fill_rect(x,y-4,2,4,(0,0,0))
|
||||
fill_rect(x,y+2,2,4,(0,0,0))
|
||||
fill_rect(back[0]-4,back[1]-4,10,10,snakeC)
|
||||
elif u==2 or u==1:
|
||||
fill_rect(x-4,y,4,2,(0,0,0))
|
||||
fill_rect(x+2,y,4,2,(0,0,0))
|
||||
fill_rect(back[0]-4,back[1]-4,10,10,snakeC)
|
||||
sleep(float(speed))
|
||||
# EPILEPSY WARNING !!!
|
||||
# snakeC=(randint(0,255),randint(0,255),randint(0,255))
|
||||
while snakeC==appleC or snakeC==bgC:
|
||||
snakeC=(randint(0,255),randint(0,255),randint(0,255))
|
||||
# beau()
|
||||
if len(snake)==640:
|
||||
if darkmode==1:
|
||||
draw_string("You win !",120,100,'white','black')
|
||||
draw_string("(You reached the max length)",20,120,'white','black')
|
||||
else:
|
||||
draw_string("You win !",120,100)
|
||||
draw_string("(You reached the max length)",20,120)
|
||||
touched=borderC
|
||||
if darkmode==1:
|
||||
draw_string("Score:"+str(score),10,10,'white','black')
|
||||
draw_string("(OK=play again, DELETE=Menu)",10,30,'white','black')
|
||||
else:
|
||||
draw_string("Score:"+str(score),10,10)
|
||||
draw_string("(OK=play again, DELETE=Menu)",10,30)
|
||||
choice=0
|
||||
while choice==0:
|
||||
if keydown(KEY_OK):
|
||||
choice=1
|
||||
launch(darkmode,speed,applePower,appleScore)
|
||||
elif keydown(KEY_BACKSPACE):
|
||||
choice=2
|
||||
menu()
|
||||
print("Score:",score)
|
||||
menu()
|
|
@ -0,0 +1,27 @@
|
|||
# This script draws a Mandelbrot fractal set
|
||||
# N_iteration: degree of precision
|
||||
import kandinsky
|
||||
import ion
|
||||
import time
|
||||
|
||||
N_iteration = 10
|
||||
|
||||
for x in range(320):
|
||||
for y in range(222):
|
||||
# Compute the mandelbrot sequence for the point c = (c_r, c_i) with start value z = (z_r, z_i)
|
||||
z = complex(0,0)
|
||||
# Rescale to fit the drawing screen 320x222
|
||||
c = complex(3.5*x/319-2.5, -2.5*y/221+1.25)
|
||||
i = 0
|
||||
while (i < N_iteration) and abs(z) < 2:
|
||||
i = i + 1
|
||||
z = z*z+c
|
||||
# Choose the color of the dot from the Mandelbrot sequence
|
||||
rgb = int(255*i/N_iteration)
|
||||
col = kandinsky.color(int(rgb),int(rgb*0.75),int(rgb*0.25))
|
||||
# Draw a pixel colored in 'col' at position (x,y)
|
||||
kandinsky.set_pixel(x,y,col)
|
||||
|
||||
while not ion.keydown(ion.KEY_EXE):
|
||||
time.sleep(0.1)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
from kandinsky import *
|
||||
from gint import *
|
||||
|
||||
draw_string( "Hello Kandinsky", 10, 10, "white", "red" )
|
||||
|
||||
draw_string( "Hello Kandinsky", 10, 200, "k" )
|
||||
|
||||
fill_rect( 25, 25, 100, 100, 00000 )
|
||||
fill_rect( 60, 25, 10, 100, 65000 )
|
||||
fill_rect( 25, 60, 100, 10, 00031 )
|
||||
|
||||
fill_rect( 100, 100, 25, 25, "green" )
|
||||
|
||||
fill_rect( 200, 100, 25, 25, (255,255,0) )
|
||||
|
||||
fill_rect( 200, 50, 25, 25, (128,0,255) )
|
||||
|
||||
set_pixel( 150, 150, "red" )
|
||||
set_pixel( 160, 160, (0,0,255) )
|
||||
|
||||
|
||||
# The following functions are only valid on fxCG (this is an extension of Kandinsky to take benefit of wide screen
|
||||
|
||||
color = "black"
|
||||
|
||||
if CGEXT_Is_Wide_Screen_Enabled() :
|
||||
color = "red"
|
||||
fill_rect( -100, 150, 500, 10, color )
|
||||
|
||||
CGEXT_Enable_Wide_Screen()
|
||||
|
||||
if CGEXT_Is_Wide_Screen_Enabled() :
|
||||
color = "green"
|
||||
else :
|
||||
color = "purple"
|
||||
fill_rect( -100, 165, 500, 10, color )
|
||||
|
||||
CGEXT_Disable_Wide_Screen()
|
||||
|
||||
if CGEXT_Is_Wide_Screen_Enabled() :
|
||||
color = "blue"
|
||||
else :
|
||||
color = "red"
|
||||
fill_rect( -100, 180, 500, 10, color )
|
||||
|
||||
getkey()
|
|
@ -0,0 +1,227 @@
|
|||
# PacMan par Kevin FEDYNA
|
||||
# https://nsi.xyz/numapps/pac-man-en-python-numworks/
|
||||
# converti sur fxCG50 et PythonExtra par SlyVTT
|
||||
|
||||
from kandinsky import fill_rect, draw_string
|
||||
from ion import keydown, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT
|
||||
from math import sqrt
|
||||
from random import randint
|
||||
from time import monotonic
|
||||
|
||||
try:
|
||||
from kandinsky import get_keys
|
||||
color = (192, 53, 53)
|
||||
except:
|
||||
color = (255, 183, 52)
|
||||
|
||||
terrain = (262143,131841,187245,187245,131073,186285,135969,252783,249903,251823,1152,251823,249903,251823,131841,187245,147465,219051,135969,195453,131073,262143)
|
||||
bits = 18
|
||||
width = 320
|
||||
height = 222
|
||||
colors = ((0, 0, 0), (32, 48, 248), (248, 224, 8), tuple(color))
|
||||
ghost_color = ((255, 184, 255), (255, 0,0), (255, 184, 82), (0, 255, 255))
|
||||
pacgommes = [0,130302,9360,74898,131070,75858,126174,8208,8208,8208,8208,8208,8208,8208,130302,74898,49140,43092,126174,66690,131070,0]
|
||||
superpacgommes = [0,0,65538,0,0,0,0,0,0,0,0,0,0,0,0,0,65538,0,0,0,0,0,0]
|
||||
frightened = 0
|
||||
lives = 2
|
||||
won = 0
|
||||
lvl = 0
|
||||
score = 0
|
||||
chained = 0
|
||||
|
||||
|
||||
class Entity:
|
||||
def __init__(self, x, y, clr, d=0):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.d = d
|
||||
self.nd = d
|
||||
self.f = 0
|
||||
self.out = 0
|
||||
self.color = clr
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,self.color)
|
||||
def espace(self,dx=-1,dy=-1):
|
||||
if dx == dy:
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[self.nd]
|
||||
return not terrain[int(self.y + 5.5*dy)]>>(bits-1-int(self.x + 5.5*dx)) & 1 and ((dx != 0 and self.y%1 == 0.5) or (dy != 0 and self.x%1== 0.5))
|
||||
def move(self):
|
||||
global frightened, ghosts, score, chained, lives, total, won
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[self.d]
|
||||
if self.espace(dx,dy):
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,colors[0])
|
||||
self.x = (round(self.x + dx, 1) - 0.5) % 16.5 + 0.5
|
||||
self.y = round(self.y + dy, 1)
|
||||
fill_rect(int(self.x*10)+136,int(self.y*10)-3,8,8,self.color)
|
||||
if self.color == colors[2]:
|
||||
if pacgommes[int(self.y)] >> (bits - 1 - int(self.x)) & 1:
|
||||
pacgommes[int(self.y)] -= 1 << (bits - 1 - int(self.x))
|
||||
score += 10
|
||||
if superpacgommes[int(self.y)] >> (bits - 1 - int(self.x)) & 1:
|
||||
superpacgommes[int(self.y)] -= 1 << (bits - 1 - int(self.x))
|
||||
score += 50
|
||||
chained = 0
|
||||
frightened = monotonic()
|
||||
for g in ghosts:
|
||||
if g.out:
|
||||
g.color = colors[1]
|
||||
g.d = (3, 2, 1, 0)[g.d]
|
||||
g.f = 1
|
||||
for g in range(4):
|
||||
if sqrt((self.x-ghosts[g].x)**2+(self.y-ghosts[g].y)**2) < 0.6:
|
||||
if ghosts[g].f:
|
||||
chained += 1
|
||||
total += 1
|
||||
score += (1 << chained)*100
|
||||
ghosts[g].f = 0
|
||||
ghosts[g].color = ghost_color[g]
|
||||
ghosts[g].x = 9
|
||||
ghosts[g].y = 8.5
|
||||
if total == 16:
|
||||
score += 12000
|
||||
else:
|
||||
for gp in range(4):
|
||||
ghosts[gp].f = 0
|
||||
ghosts[gp].color = ghost_color[gp]
|
||||
ghosts[gp].x = 9
|
||||
ghosts[gp].y = 10.5
|
||||
ghosts[gp].out = 0
|
||||
self.x = 9
|
||||
self.y = 16.5
|
||||
self.d, self.nd = 0, 0
|
||||
lives -= 1
|
||||
return render()
|
||||
if not won and score > 10000:
|
||||
lives += 1
|
||||
won = 1
|
||||
px, py = int(self.x - 5.5*dx), int(self.y - 5.5*dy)
|
||||
if pacgommes[py]>>(bits-1-px) & 1:
|
||||
fill_rect(px*10+144,py*10+5,2,2,(250, 207, 173))
|
||||
if superpacgommes[py]>>(bits-1-px) & 1:
|
||||
fill_rect(px*10+143,py*10+4,4,4,(250, 207, 173))
|
||||
def ia(self,x,y):
|
||||
if self.f:
|
||||
while True:
|
||||
d = randint(0,3)
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[d]
|
||||
if d != (3,2,1,0)[self.d] and self.espace(dx,dy):
|
||||
self.d = d
|
||||
break
|
||||
else:
|
||||
distances = [9999 for _ in range(4)]
|
||||
for i in range(4):
|
||||
if i != (3,2,1,0)[self.d]:
|
||||
dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[i]
|
||||
if self.espace(dx,dy):
|
||||
distances[i] = sqrt((self.y + dy - y)**2 + (self.x + dx - x)**2)
|
||||
self.d = distances.index(min(distances))
|
||||
|
||||
def prebuild():
|
||||
fill_rect(0,0,width,height,colors[0])
|
||||
fill_rect(138, 0, 2, height, colors[3])
|
||||
draw_string("PAC-MAN", 35, 10, colors[3], colors[0])
|
||||
draw_string("nsi.xyz/pacman", 0, 204,colors[0], colors[3])
|
||||
draw_string("Score :", 35, 40, (255,)*3, colors[0])
|
||||
draw_string("Niveau :", 30, 90, (255,)*3, colors[0])
|
||||
|
||||
def render():
|
||||
global terrain, pacgommes, superpacgommes, lives, arrivee
|
||||
if lives == -1:
|
||||
return 42
|
||||
draw_string(str(lvl),70-5*len(str(lvl)),110,(255,)*3,colors[0])
|
||||
fill_rect(0,150,138,20,colors[0])
|
||||
for i in range(lives):
|
||||
fill_rect(60-(lives-1)*20+i*40,150,20,20,colors[2])
|
||||
for l in range(len(terrain)):
|
||||
for c in range(bits):
|
||||
fill_rect(c*10+140,l*10+1,10,10,colors[0])
|
||||
if pacgommes[l]>>(bits-1-c) & 1:
|
||||
fill_rect(c*10+144,l*10+5,2,2,(250, 207, 173))
|
||||
if superpacgommes[l]>>(bits-1-c) & 1:
|
||||
fill_rect(c*10+143,l*10+4,4,4,(250, 207, 173))
|
||||
if terrain[l]>>(bits-1-c) & 1:
|
||||
for d in ((1,0),(0,1),(-1,0),(0,-1)):
|
||||
if 0 <= l + d[0] <= len(terrain) - 1 and 0 <= c + d[1] <= bits - 1 and not terrain[l + d[0]]>>(bits-1-(c+d[1])) & 1:
|
||||
fill_rect(c*10+140+9*(d[1]==1),l*10+1+9*(d[0]==1),1+9*(d[1]==0),1+9*(d[0]==0),colors[1])
|
||||
arrivee = monotonic()
|
||||
|
||||
def engine():
|
||||
global frightened, ghosts, pacgommes, superpacgommes, lvl, arrivee, total
|
||||
while True:
|
||||
pacgommes = [0,130302,9360,74898,131070,75858,126174,8208,8208,8208,8208,8208,8208,8208,130302,74898,49140,43092,126174,66690,131070,0]
|
||||
superpacgommes = [0,0,65538,0,0,0,0,0,0,0,0,0,0,0,0,0,65538,0,0,0,0,0,0]
|
||||
lvl += 1
|
||||
total = 0
|
||||
render()
|
||||
pacman = Entity(9, 16.5, colors[2])
|
||||
ghosts = [Entity(9, 10.5, ghost_color[i]) for i in range(4)]
|
||||
while sum(pacgommes) + sum(superpacgommes):
|
||||
depart = monotonic()
|
||||
lk=[KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT]
|
||||
for i in range(4):
|
||||
if keydown(lk[i]):
|
||||
if i == (3,2,1,0)[pacman.d]:
|
||||
pacman.d = i
|
||||
pacman.nd = i
|
||||
while monotonic() - depart < 0.01:
|
||||
if pacman.espace():
|
||||
pacman.d = pacman.nd
|
||||
if pacman.move() == 42:
|
||||
draw_string("GAME OVER",185,100,colors[3],colors[0])
|
||||
return 69
|
||||
|
||||
draw_string(str(score),70-5*len(str(score)),60,(255,)*3,colors[0])
|
||||
|
||||
""" Fantomes """
|
||||
|
||||
if frightened:
|
||||
if monotonic() - frightened > 6.5:
|
||||
for g in ghosts:
|
||||
if g.f:
|
||||
g.color = (255,)*3
|
||||
if monotonic() - frightened > 8.5:
|
||||
frightened = 0
|
||||
for g in range(4):
|
||||
ghosts[g].color = ghost_color[g]
|
||||
ghosts[g].f = 0
|
||||
|
||||
if arrivee:
|
||||
if monotonic() - arrivee > 0 and not ghosts[1].out:
|
||||
ghosts[1].out = 1
|
||||
ghosts[1].y = 8.5
|
||||
if monotonic() - arrivee > 2.5 and not ghosts[0].out:
|
||||
ghosts[0].out = 1
|
||||
ghosts[0].y = 8.5
|
||||
if monotonic() - arrivee > 5 and not ghosts[3].out:
|
||||
ghosts[3].out = 1
|
||||
ghosts[3].y = 8.5
|
||||
if monotonic() - arrivee > 7.5 and not ghosts[2].out:
|
||||
ghosts[2].out = 1
|
||||
ghosts[2].y = 8.5
|
||||
fill_rect(220,101,20,10,colors[0])
|
||||
arrivee = 0
|
||||
|
||||
pdx, pdy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[pacman.d]
|
||||
|
||||
# Pinky
|
||||
ghosts[0].ia(pacman.x + 20 * pdx, pacman.y + 20 * pdy)
|
||||
ghosts[0].move()
|
||||
|
||||
# Inky
|
||||
ghosts[3].ia(max(min(ghosts[1].x + 2*(pacman.x + 20 * pdx - ghosts[1].x), 16.5), 1.5), max(min(ghosts[1].y +2*(pacman.y + 20 * pdy - ghosts[1].y), 21.5), 1.5))
|
||||
ghosts[3].move()
|
||||
|
||||
# Blinky
|
||||
ghosts[1].ia(pacman.x, pacman.y)
|
||||
ghosts[1].move()
|
||||
|
||||
# Clyde
|
||||
if sqrt((ghosts[2].x - pacman.x)**2 + (ghosts[2].y - pacman.y)**2) > 4:
|
||||
ghosts[2].ia(pacman.x, pacman.y)
|
||||
else:
|
||||
ghosts[2].ia(1.5, 20.5)
|
||||
ghosts[2].move()
|
||||
|
||||
|
||||
fill_rect(0,0,319,219,"black")
|
||||
prebuild()
|
||||
engine()
|
|
@ -0,0 +1,77 @@
|
|||
from kandinsky import *
|
||||
from math import *
|
||||
import ion
|
||||
import time
|
||||
|
||||
def cercle1(x0,y0,r,c,e):
|
||||
for i in range(2*e):
|
||||
xd=x0-int((r-i*0.5)/sqrt(2))
|
||||
xf=x0+int((r-i*0.5)/sqrt(2))
|
||||
for x in range(xd,xf+1):
|
||||
x1=x
|
||||
y1=y0+int(sqrt((r-i*0.5)**2-(x-x0)**2))
|
||||
if sqrt((160-x1)**2+(111-y1)**2)<r:
|
||||
set_pixel(x1,y1,c)
|
||||
for j in range(3):
|
||||
x2=x0+y1-y0
|
||||
y2=y0+x0-x1
|
||||
if sqrt((160-x2)**2+(111-y2)**2)<r:
|
||||
set_pixel(x2,y2,c)
|
||||
x1,y1=x2,y2
|
||||
|
||||
def cercle2(x0,y0,r,c,e):
|
||||
for i in range(2*e):
|
||||
xd=x0-int((r-i*0.5)/sqrt(2))
|
||||
xf=x0+int((r-i*0.5)/sqrt(2))
|
||||
for x in range(xd,xf+1):
|
||||
x1=x
|
||||
y1=y0+int(sqrt((r-i*0.5)**2-(x-x0)**2))
|
||||
set_pixel(x,y1,c)
|
||||
for j in range(3):
|
||||
x2=x0+y1-y0
|
||||
y2=y0+x0-x1
|
||||
set_pixel(x2,y2,c)
|
||||
x1,y1=x2,y2
|
||||
|
||||
def rosace1(n,r,c,e):
|
||||
x,y=160+r,111
|
||||
for i in range(n):
|
||||
x1=int(160+r*cos(i*2*pi/n))
|
||||
y1=int(111+r*sin(i*2*pi/n))
|
||||
cercle1(x1,y1,r,c,e)
|
||||
cercle1(160,111,r,c,e)
|
||||
|
||||
def rosace2(n,r,c,e):
|
||||
x,y=160+r,111
|
||||
for i in range(n):
|
||||
x1=int(160+r*cos(i*2*pi/n))
|
||||
y1=int(111+r*sin(i*2*pi/n))
|
||||
cercle2(x1,y1,r,c,e)
|
||||
|
||||
def rosace3(n,r,c1,c2,c3,e):
|
||||
for k in range(2):
|
||||
rj=r
|
||||
for j in range(n-2):
|
||||
rj=int(rj-rj/(2*n))
|
||||
if k==0:rj+=1
|
||||
x,y=160+rj,111
|
||||
for i in range(n):
|
||||
x1=int(160+rj*cos(i*2*pi/n))
|
||||
y1=int(111+rj*sin(i*2*pi/n))
|
||||
if k==0:
|
||||
col=c3
|
||||
else:
|
||||
if j==0 or j>n-4:col=c2
|
||||
else:col=c1
|
||||
cercle2(x1,y1,rj,col,e)
|
||||
|
||||
|
||||
col1=color(5,50,120)
|
||||
col2=color(255,45,45)
|
||||
col3=color(245,225,25)
|
||||
#rosace1(12,50,col1,2)
|
||||
#rosace2(12,50,col1,1)
|
||||
rosace3(10,55,col1,col2,col3,1)
|
||||
|
||||
while not ion.keydown(ion.KEY_EXE):
|
||||
time.sleep(0.1)
|
|
@ -0,0 +1,326 @@
|
|||
# Snake from Golem64
|
||||
# https://my.numworks.com/python/golem64/snake
|
||||
#
|
||||
# converted to PythonExtra on fx-CG50 by SlyVTT
|
||||
#
|
||||
# Version 1.7 STABLE
|
||||
# Tip: You should try to press
|
||||
# some keys in the menu...
|
||||
|
||||
from random import *
|
||||
from kandinsky import *
|
||||
from ion import *
|
||||
from time import *
|
||||
|
||||
def oscolor():
|
||||
try:
|
||||
get_keys()
|
||||
except:
|
||||
return 'orange'
|
||||
else:
|
||||
return 'red'
|
||||
|
||||
def lastPos(i,x,y):
|
||||
if i[-1]==3:
|
||||
pos=[x-10,y]
|
||||
elif i[-1]==2:
|
||||
pos=[x,y-10]
|
||||
elif i[-1]==0:
|
||||
pos=[x+10,y]
|
||||
elif i[-1]==1:
|
||||
pos=[x,y+10]
|
||||
pos[0],pos[1]=checkTeleport(pos[0],pos[1])
|
||||
return pos
|
||||
|
||||
def newApple(appleC,bgC):
|
||||
applex=randint(0,31)*10+4
|
||||
appley=randint(0,21)*10+5
|
||||
while get_pixel(applex,appley)!=bgC:
|
||||
applex=randint(0,31)*10+4
|
||||
appley=randint(0,21)*10+5
|
||||
fill_rect(applex-4,appley-4,10,10,appleC)
|
||||
return applex,appley
|
||||
|
||||
def checkTeleport(x,y):
|
||||
if x<4:
|
||||
x=314
|
||||
if x>314:
|
||||
x=4
|
||||
if y<5:
|
||||
y=215
|
||||
if y>215:
|
||||
y=5
|
||||
return x,y
|
||||
|
||||
def getMove(u):
|
||||
lk=[KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT]
|
||||
for k in range(4):
|
||||
if keydown(lk[k])==True and u+k!=3: return k
|
||||
return u
|
||||
|
||||
def clearDraw():
|
||||
fill_rect(0,0,320,222,(255,255,255))
|
||||
|
||||
def clearHome():
|
||||
print("\n \n \n \n \n \n \n \n \n \n \n \n \n ")
|
||||
|
||||
def redraw():
|
||||
draw_string("(DELETE to exit)",0,0)
|
||||
printLetter([1,1,1,1,0,0,1,1,1,0,0,1,1,1,1],70,80,10,(0,204,0))
|
||||
fill_rect(95,80,2,4,(0,0,0))
|
||||
fill_rect(95,86,2,4,(0,0,0))
|
||||
fill_rect(100,84,4,2,(255,0,0))
|
||||
fill_rect(104,82,2,2,(255,0,0))
|
||||
fill_rect(104,86,2,2,(255,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,0,1,1,0,1,1,0,1],110,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,1,1,1,0,1,1,0,1],150,80,10,(0,0,0))
|
||||
printLetter([1,0,1,1,0,1,1,1,0,1,0,1,1,0,1],190,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,0,1,1,1,1,0,0,1,1,1],230,80,10,(0,0,0))
|
||||
|
||||
def printLetter(letter,x,y,size,color):
|
||||
for yi in range(5):
|
||||
for xi in range(3):
|
||||
if letter[yi*3+xi]==1:
|
||||
fill_rect(x+(xi*size),y+(yi*size),size,size,color)
|
||||
|
||||
def menu():
|
||||
clearDraw()
|
||||
printLetter([1,1,1,1,0,1,1,0,1,1,0,1,1,0,1],110,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,1,1,1,1,1,0,1,1,0,1],150,80,10,(0,0,0))
|
||||
printLetter([1,0,1,1,0,1,1,1,0,1,0,1,1,0,1],190,80,10,(0,0,0))
|
||||
printLetter([1,1,1,1,0,0,1,1,1,1,0,0,1,1,1],230,80,10,(0,0,0))
|
||||
anim=[1,1,1,1,1,1,1,1,1,4,4,3,3,4,4,1,1]
|
||||
ax=0
|
||||
ay=120
|
||||
aendx=-110
|
||||
aendy=120
|
||||
u=1
|
||||
aback=0
|
||||
for i in range(len(anim)):
|
||||
ax=ax+((anim[i]==1)-(anim[i]==3))*10
|
||||
ay=ay+((anim[i]==2)-(anim[i]==4))*10
|
||||
if aendx<0:
|
||||
aendx=aendx+10
|
||||
else:
|
||||
aendx=aendx+((anim[i-11]==1)-(anim[i-11]==3))*10
|
||||
aendy=aendy+((anim[i-11]==2)-(anim[i-11]==4))*10
|
||||
fill_rect(aendx,aendy,10,10,(255,255,255))
|
||||
fill_rect(ax,ay,10,10,(0,204,0))
|
||||
# aback=lastPos(anim,ax,ay)
|
||||
# if u==26 or u==24:
|
||||
# fill_rect(ax-1,ay-1,3,1,(0,0,0))
|
||||
# fill_rect(ax-1,ay+1,3,1,(0,0,0))
|
||||
# fill_rect(aback[0],aback[1],10,10,(0,204,0))
|
||||
# elif u==34 or u==25:
|
||||
# fill_rect(ax-1,ay-1,1,3,(0,0,0))
|
||||
# fill_rect(ax+1,ay-1,1,3,(0,0,0))
|
||||
# fill_rect(aback[0]-2,aback[1]-2,5,5,(0,204,0))
|
||||
sleep(0.05)
|
||||
fill_rect(ax+5,ay,2,4,(0,0,0))
|
||||
fill_rect(ax+5,ay+6,2,4,(0,0,0))
|
||||
fill_rect(ax+10,ay+4,4,2,(255,0,0))
|
||||
fill_rect(ax+14,ay+2,2,2,(255,0,0))
|
||||
fill_rect(ax+14,ay+6,2,2,(255,0,0))
|
||||
draw_string("(DELETE to exit)",0,0)
|
||||
draw_string("> Play <",125,140,oscolor())
|
||||
draw_string(" Options ",110,165)
|
||||
darkMode=0
|
||||
Speed=0.05
|
||||
power=5
|
||||
score=1
|
||||
exit=0
|
||||
sel=1
|
||||
while keydown(KEY_OK)!=True and exit==0:
|
||||
if keydown(KEY_DOWN) and sel==1:
|
||||
draw_string(" Play ",125,140)
|
||||
draw_string("> Options <",110,165,oscolor())
|
||||
sel=2
|
||||
elif keydown(KEY_UP) and sel==2:
|
||||
draw_string("> Play <",125,140,oscolor())
|
||||
draw_string(" Options ",110,165)
|
||||
sel=1
|
||||
if keydown(KEY_LEFTPARENTHESIS) and keydown(KEY_RIGHTPARENTHESIS):
|
||||
draw_string("Dark mode enabled !",80,195)
|
||||
darkMode=1
|
||||
if keydown(KEY_BACKSPACE):
|
||||
exit=1
|
||||
sleep(0.1)
|
||||
if sel==2 and exit!=1:
|
||||
fill_rect(0,130,300,60,(255,255,255))
|
||||
Speed=0.05
|
||||
power=5
|
||||
score=1
|
||||
draw_string("Speed:"+str(Speed),50,140,oscolor(),'white')
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
sel=1
|
||||
sleep(0.2)
|
||||
while keydown(KEY_OK)!=True or sel!=4:
|
||||
if keydown(KEY_RIGHT):
|
||||
sel=sel+1
|
||||
elif keydown(KEY_DOWN):
|
||||
sel=sel+2
|
||||
elif keydown(KEY_LEFT):
|
||||
sel=sel-1
|
||||
elif keydown(KEY_UP):
|
||||
sel=sel-2
|
||||
if sel<0:
|
||||
sel=0
|
||||
if sel>4:
|
||||
sel=4
|
||||
if sel==1:
|
||||
draw_string("Speed:"+str(Speed),50,140,oscolor(),'white')
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
Speed=input("Speed:")
|
||||
redraw()
|
||||
elif sel==2:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140,oscolor(),'white')
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
power=int(input("Power:+"))
|
||||
redraw()
|
||||
elif sel==3:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170,oscolor(),'white')
|
||||
draw_string("Play",220,170)
|
||||
if keydown(KEY_OK):
|
||||
clearHome()
|
||||
score=int(input("Score:"))
|
||||
redraw()
|
||||
elif sel==4:
|
||||
draw_string("Speed:"+str(Speed),50,140)
|
||||
draw_string("Power:+"+str(power),200,140)
|
||||
draw_string("Score:+"+str(score),50,170)
|
||||
draw_string("Play",220,170,oscolor(),'white')
|
||||
if (keydown(KEY_LEFTPARENTHESIS) and keydown(KEY_RIGHTPARENTHESIS)) or darkMode==1:
|
||||
draw_string("Dark mode enabled !",80,195)
|
||||
darkMode=1
|
||||
if keydown(KEY_BACKSPACE):
|
||||
exit=1
|
||||
break
|
||||
sleep(0.1)
|
||||
if exit!=1:
|
||||
if darkMode==1:
|
||||
launch(1,Speed,power,score)
|
||||
elif darkMode==0:
|
||||
launch(0,Speed,power,score)
|
||||
elif exit==1:
|
||||
clearDraw()
|
||||
return
|
||||
|
||||
def launch(darkmode=0,speed=0.05,applePower=5,appleScore=1):
|
||||
bgC=(248,252,248)
|
||||
borderC=(0,0,0)
|
||||
snakeC=(0,204,0)
|
||||
appleC=(248,0,0)
|
||||
if darkmode==1:
|
||||
bgC=(0,0,0)
|
||||
borderC=(0,0,204)
|
||||
fill_rect(0,0,320,222,bgC)
|
||||
# fill_rect(315,0,5,222,borderC)
|
||||
# fill_rect(0,0,5,222,borderC)
|
||||
# fill_rect(0,0,320,1,(197,52,49))
|
||||
fill_rect(0,221,320,1,(0,0,0))
|
||||
try:
|
||||
get_keys()
|
||||
except:
|
||||
fill_rect(0,0,320,1,(255,181,49))
|
||||
else:
|
||||
fill_rect(0,0,320,1,(197,52,49))
|
||||
snake=[3,3,3,3,3]
|
||||
x=154
|
||||
y=115
|
||||
endx=104
|
||||
endy=115
|
||||
u,v=3,3
|
||||
length=5
|
||||
applex,appley=newApple(appleC,bgC)
|
||||
score,touched=0,0
|
||||
while touched!=borderC and touched!=snakeC:
|
||||
if keydown(KEY_LEFT) or keydown(KEY_UP) or keydown(KEY_DOWN) or keydown(KEY_RIGHT):
|
||||
u=getMove(u)
|
||||
if keydown(KEY_BACKSPACE):
|
||||
while keydown(KEY_BACKSPACE):
|
||||
sleep(0.1)
|
||||
while keydown(KEY_BACKSPACE)!=True:
|
||||
sleep(0.1)
|
||||
while keydown(KEY_BACKSPACE):
|
||||
sleep(0.1)
|
||||
snake.append(u)
|
||||
if x==applex and y==appley:
|
||||
length=length+float(applePower)
|
||||
applex,appley=newApple(appleC,bgC)
|
||||
score=score+int(appleScore)
|
||||
x=x+((u==3)-(u==0))*10
|
||||
y=y+((u==2)-(u==1))*10
|
||||
x,y=checkTeleport(x,y)
|
||||
if length:
|
||||
length=length-1
|
||||
else:
|
||||
snake.remove(snake[0])
|
||||
endx=endx+((v==3)-(v==0))*10
|
||||
endy=endy+((v==2)-(v==1))*10
|
||||
endx,endy=checkTeleport(endx,endy)
|
||||
v=snake[0]
|
||||
fill_rect(endx-4,endy-4,10,10,bgC)
|
||||
touched=get_pixel(x,y)
|
||||
if x<0 or x>320 or y<0 or y>220:
|
||||
touched=borderC
|
||||
if touched!=appleC and touched!=bgC:
|
||||
touched=borderC
|
||||
fill_rect(x-4,y-4,10,10,snakeC)
|
||||
back=lastPos(snake,x,y)
|
||||
if u==3 or u==0:
|
||||
fill_rect(x,y-4,2,4,(0,0,0))
|
||||
fill_rect(x,y+2,2,4,(0,0,0))
|
||||
fill_rect(back[0]-4,back[1]-4,10,10,snakeC)
|
||||
elif u==2 or u==1:
|
||||
fill_rect(x-4,y,4,2,(0,0,0))
|
||||
fill_rect(x+2,y,4,2,(0,0,0))
|
||||
fill_rect(back[0]-4,back[1]-4,10,10,snakeC)
|
||||
sleep(float(speed))
|
||||
# EPILEPSY WARNING !!!
|
||||
# snakeC=(randint(0,255),randint(0,255),randint(0,255))
|
||||
while snakeC==appleC or snakeC==bgC:
|
||||
snakeC=(randint(0,255),randint(0,255),randint(0,255))
|
||||
# beau()
|
||||
if len(snake)==640:
|
||||
if darkmode==1:
|
||||
draw_string("You win !",120,100,'white','black')
|
||||
draw_string("(You reached the max length)",20,120,'white','black')
|
||||
else:
|
||||
draw_string("You win !",120,100)
|
||||
draw_string("(You reached the max length)",20,120)
|
||||
touched=borderC
|
||||
if darkmode==1:
|
||||
draw_string("Score:"+str(score),10,10,'white','black')
|
||||
draw_string("(OK=play again, DELETE=Menu)",10,30,'white','black')
|
||||
else:
|
||||
draw_string("Score:"+str(score),10,10)
|
||||
draw_string("(OK=play again, DELETE=Menu)",10,30)
|
||||
choice=0
|
||||
while choice==0:
|
||||
if keydown(KEY_OK):
|
||||
choice=1
|
||||
launch(darkmode,speed,applePower,appleScore)
|
||||
elif keydown(KEY_BACKSPACE):
|
||||
choice=2
|
||||
menu()
|
||||
print("Score:",score)
|
||||
|
||||
|
||||
try:
|
||||
CGEXT_Set_Margin_Color( "black" )
|
||||
except:
|
||||
print("fxCG Extension not supported")
|
||||
|
||||
menu()
|
|
@ -0,0 +1,15 @@
|
|||
from time import *
|
||||
|
||||
print(monotonic())
|
||||
|
||||
sleep(1)
|
||||
|
||||
print(monotonic())
|
||||
|
||||
sleep(2)
|
||||
|
||||
print(monotonic())
|
||||
|
||||
sleep(1)
|
||||
|
||||
print(monotonic())
|
|
@ -0,0 +1,4 @@
|
|||
from kandinsky import *
|
||||
|
||||
# Check whether global dwindow from kandisky interferes with shell
|
||||
input("Happy? (y/n): ")
|
|
@ -0,0 +1,8 @@
|
|||
from polycal4 import get_infos
|
||||
from synchrod import *
|
||||
|
||||
def tour(plateau, joueurs, evenements):
|
||||
# Demander une action avec input()
|
||||
return demander_action()
|
||||
|
||||
play_game(tour)
|
|
@ -0,0 +1,58 @@
|
|||
from polycal4 import get_infos
|
||||
from synchrod import *
|
||||
|
||||
# Ordre des joueurs à sortir
|
||||
ordre_de_sortie = [0, 2, 1, 3]
|
||||
# Position du joueur qu'on veut sortir dans ordre_de_sortie
|
||||
joueur_courant_id = 0
|
||||
# Chemin pour le sortir
|
||||
chemin = []
|
||||
|
||||
def tour(plateau, joueurs, evenements):
|
||||
global joueur_courant_id, chemin
|
||||
|
||||
for (x, y, ev, joueur) in evenements:
|
||||
if ev == NOUVELLE_PARTIE:
|
||||
joueur_courant_id = 0
|
||||
chemin = []
|
||||
|
||||
# Si le joueur est arrivé à sa destination, on passe au suivant
|
||||
while joueurs[ordre_de_sortie[joueur_courant_id]] == -1:
|
||||
joueur_courant_id += 1
|
||||
chemin = []
|
||||
|
||||
joueur_courant = ordre_de_sortie[joueur_courant_id]
|
||||
|
||||
# Chemin du joueur actuel vers sa sortie
|
||||
if chemin == []:
|
||||
case_sortie = plateau.index(SORTIE + joueur_courant)
|
||||
chemin = calculer_chemin(plateau, joueurs[joueur_courant], case_sortie)
|
||||
|
||||
# S'il y a des monstres autour mais pas de piège, attaquer
|
||||
monstres_autour = False
|
||||
pieges_autour = False
|
||||
|
||||
for joueur in joueurs:
|
||||
# On ne compte pas les joueurs qui ont déjà sortis
|
||||
if joueur != -1:
|
||||
if est_un(plateau[joueur-1], MONSTRE) or \
|
||||
est_un(plateau[joueur+1], MONSTRE) or \
|
||||
est_un(plateau[joueur-16], MONSTRE) or \
|
||||
est_un(plateau[joueur+16], MONSTRE):
|
||||
monstres_autour = True
|
||||
if est_un(plateau[joueur-1], PIEGE) or \
|
||||
est_un(plateau[joueur+1], PIEGE) or \
|
||||
est_un(plateau[joueur-16], PIEGE) or \
|
||||
est_un(plateau[joueur+16], PIEGE):
|
||||
pieges_autour = True
|
||||
|
||||
# if monstres_autour and not pieges_autour:
|
||||
# return ATTAQUER
|
||||
|
||||
# Prochaine étape
|
||||
mouvement = chemin[0]
|
||||
chemin = chemin[1:]
|
||||
|
||||
return mouvement
|
||||
|
||||
play_game(tour, blind=True)
|
|
@ -0,0 +1,512 @@
|
|||
#cas
|
||||
from math import pi, asin
|
||||
|
||||
KEY_NONE, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_ENTER, KEY_ESC, KEY_7, KEY_8, KEY_9, KEY_LEFT_PARENTHESIS, KEY_RIGHT_PARENTHESIS, KEY_4, KEY_5, KEY_6, KEY_1, KEY_2, KEY_3, KEY_0 = 0, 1, 2, 3, 4, 53, 6, 30, 31, 32, 34, 35, 36, 37, 38, 42, 43, 44, 48
|
||||
|
||||
def fix_angle(a):
|
||||
return a * 2 * asin(1) / pi
|
||||
def col3_2_rgb(c, bits, bgr):
|
||||
return c[2*bgr]//2**(8 - bits[0]) + c[1]//2**(8 - bits[1])*2**bits[0] + c[2*(not(bgr))]//2**(8-bits[2])*2**(bits[0] + bits[1])
|
||||
|
||||
def hp_draw_line(x1, y1, x2, y2, c):
|
||||
line_p(x1, y1, x2, y2, col3_2_rgb(c, [8, 8, 8], 1))
|
||||
def hp_fill_rect(x, y, w, h, c):
|
||||
rect_p(x, y, x + w - 1, y + h - 1, col3_2_rgb(c, [8, 8, 8], 1))
|
||||
def hp_draw_circle(x, y, r, c):
|
||||
global L1
|
||||
c = col3_2_rgb(c, [8, 8, 8], 1)
|
||||
arc_p(x, y, r, 0, fix_angle(2*pi), c)
|
||||
def hp_fill_circle(x, y, r, c):
|
||||
global L1, L2
|
||||
c = col3_2_rgb(c, [8, 8, 8], 1)
|
||||
L2 = [c, c]
|
||||
arc_p(x, y, r, 0, fix_angle(2*pi), L2)
|
||||
def hp_draw_ellipse(x, y, rx, ry, c):
|
||||
global L1
|
||||
c, L1 = col3_2_rgb(c, [8, 8, 8], 1), [rx, ry]
|
||||
arc_p(x, y, L1, 0, fix_angle(2*pi), c)
|
||||
def hp_fill_ellipse(x, y, rx, ry, c):
|
||||
global L1, L2
|
||||
c, L1 = col3_2_rgb(c, [8, 8, 8], 1), [rx, ry]
|
||||
L2 = [c, c]
|
||||
arc_p(x, y, L1, 0, fix_angle(2*pi), L2)
|
||||
def hp_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
textout_p(s, x, y, 1, col3_2_rgb(cf, [8, 8, 8], 1), len(s) * 9, col3_2_rgb(cb, [8, 8, 8], 1))
|
||||
def hp_clear_screen():
|
||||
rect_p(0, 0, 319, 239, 16777215)
|
||||
def hp_pause():
|
||||
wait()
|
||||
def hp_sleep(d):
|
||||
wait(d)
|
||||
def hp_monotonic(d):
|
||||
return time()
|
||||
def hp_get_key():
|
||||
d_key = {KEY_LEFT:7, KEY_UP:2, KEY_DOWN:12, KEY_RIGHT:8, KEY_ENTER:30, KEY_ESC:4, KEY_LEFT_PARENTHESIS:28, KEY_0:47, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:37, KEY_5:38, KEY_6:39, KEY_7:32, KEY_8:33, KEY_9:34 }
|
||||
key = get_key()
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
|
||||
def kc1_draw_line(x1, y1, x2, y2, c):
|
||||
draw_line(float(x1), float(y1), float(x2), float(y2), not(col3_2_rgb(c, [1, 1, 1], 0)))
|
||||
def kc1_fill_rect(x, y, w, h, c):
|
||||
draw_rectangle(float(x), float(y), float(w), float(h), (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
|
||||
def kc1_draw_circle(x, y, r, c):
|
||||
draw_arc(float(x), float(y), float(r), not (col3_2_rgb(c, [1, 1, 1], 0)))
|
||||
def kc1_fill_circle(x, y, r, c):
|
||||
draw_arc(float(x), float(y), float(r), (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
|
||||
def kc1_draw_ellipse(x, y, rx, ry, c):
|
||||
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, not (col3_2_rgb(c, [1, 1, 1], 0)))
|
||||
def kc1_fill_ellipse(x, y, rx, ry, c):
|
||||
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
|
||||
def kc1_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
draw_string(s, float(x), float(y), col3_2_rgb(cf, [1, 1, 1], 1), col3_2_rgb(cb, [1, 1, 1], 1))
|
||||
def kc_get_key():
|
||||
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:30004, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41, KEY_0:48, KEY_1:49, KEY_2:50, KEY_3:51, KEY_4:52, KEY_5:53, KEY_6:54, KEY_7:55, KEY_8:56, KEY_9:57 }
|
||||
key = get_key()
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
|
||||
tcanvas = None
|
||||
|
||||
def get_infos(keys, sdl_width=640, sdl_height=480, sdl_scale=1):
|
||||
global hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, kc1_draw_line, kc1_fill_rect, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string, hp_clear_screen, hp_pause, tcanvas
|
||||
fnop = lambda : None
|
||||
ffalse = lambda : False
|
||||
screen_w, screen_h, screen_y0, color_bits, font_w, font_num_w, font_h, poly_has_color, poly_get_pixel, poly_set_pixel, poly_show, poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_monotonic, poly_sleep, poly_draw_string, poly_clear_screen, poly_pause, poly_set_buffer, poly_get_key, poly_wait_key, poly_wait_release, poly_test_key, poly_esc_key, show_need_pause_on_exit, screen_need_clear_on_init, need_clear, need_line, need_rect, need_ellipse, need_string, need_monotonic, need_sleep, has_keys = 0, 0, 0, [5, 6, 5], 0, 0, 0, 1, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, ffalse, ffalse, ffalse, ffalse, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1
|
||||
try:
|
||||
import polycalc_sdl2
|
||||
polycalc_sdl2.polycalc_pc_init(sdl_width, sdl_height, sdl_scale)
|
||||
screen_w, screen_h, poly_set_pixel, poly_clean_screen, poly_show, poly_pause, poly_wait_key, poly_get_key, poly_test_key = polycalc_sdl2.screen_w, polycalc_sdl2.screen_h, polycalc_sdl2.poly_set_pixel, polycalc_sdl2.poly_clean_screen, polycalc_sdl2.poly_show, polycalc_sdl2.poly_pause, polycalc_sdl2.poly_wait_key, polycalc_sdl2.poly_get_key, polycalc_sdl2.poly_test_key
|
||||
color_bits = [8, 8, 8]
|
||||
poly_has_color = 1
|
||||
show_need_pause_on_exit = 0
|
||||
except:
|
||||
pass
|
||||
if not (screen_w):
|
||||
try:
|
||||
if chr(256)==chr(0): # KhiCAS Python compat.
|
||||
need_line, need_rect, need_ellipse, need_string, need_sleep, need_monotonic = 0, 0, 0, 0, 0, 0
|
||||
if "HP" in version():
|
||||
kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string = None, None, None, None, None, None, None
|
||||
screen_w, screen_h, font_w, font_h, show_need_pause_on_exit = 320, 240, 9, 11, 1
|
||||
font_num_w = font_w
|
||||
def poly_set_pixel(x, y, c):
|
||||
set_pixel(x, y, col3_2_rgb(c, [8, 8, 8], 1))
|
||||
poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_draw_string, poly_clear_screen, poly_pause, poly_sleep, poly_monotonic = hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_hp_draw_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, hp_clear_screen, hp_pause, hp_sleep, hp_monotonic
|
||||
else: # Graph 35+E II / NumWorks or Nspire / Graph 90+E
|
||||
hp_draw_line, hp_fill_rect, hp_draw_string, hp_clear_screen, hp_pause = None, None, None, None, None
|
||||
t_mono, t_nw, t_ns, need_clear = not (white), "Numworks" in version(), "Nspire" in version(), 1
|
||||
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_pause, poly_sleep = 384 - (t_ns or t_nw)*64 - t_mono*256, 192 + (t_ns or t_nw)*30 - t_mono*128, get_pixel, 10 - 4*t_mono + 5*t_ns + t_nw, 10 - 5*t_mono + 8*(t_ns or t_nw), getKey, sleep
|
||||
font_num_w = font_w
|
||||
def poly_monotonic():
|
||||
return monotonic / (1 + (not(t_nw or t_ns))*99)
|
||||
key_d = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:4, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41}
|
||||
def poly_wait_key():
|
||||
key = get_key()
|
||||
for k in key_d:
|
||||
if key == key_d[k]:
|
||||
return k
|
||||
return 0
|
||||
if t_mono:
|
||||
def poly_set_pixel(x, y, c):
|
||||
set_pixel(x, y, not(col3_2_rgb(c, [1,1,1], 0)))
|
||||
poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_draw_string = kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string
|
||||
else:
|
||||
kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string = None, None, None, None, None, None, None
|
||||
def poly_set_pixel(x, y, c):
|
||||
set_pixel(x, y, col3_2_rgb(c, [5,6,5], 0))
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
draw_line(float(x1), float(y1), float(x2), float(y2), col3_2_rgb(c, color_bits, 1))
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
draw_rectangle(float(x), float(y), float(w), float(h), col3_2_rgb(c, color_bits, 1) + filled)
|
||||
def poly_draw_circle(x, y, r, c):
|
||||
draw_arc(float(x), float(y), float(r), float(r), 0, 2*pi, col3_2_rgb(c, color_bits, 1))
|
||||
def poly_fill_circle(x, y, r, c):
|
||||
draw_arc(float(x), float(y), float(r), float(r), 0, 2*pi, col3_2_rgb(c, color_bits, 1) + filled)
|
||||
def poly_draw_ellipse(x, y, rx, ry, c):
|
||||
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, col3_2_rgb(c, color_bits, 1))
|
||||
def poly_fill_ellipse(x, y, rx, ry, c):
|
||||
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, col3_2_rgb(c, color_bits, 1) + filled)
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
draw_string(s, float(x), float(y), col3_2_rgb(cf, color_bits, 1), col3_2_rgb(cb, color_bits, 1))
|
||||
except:
|
||||
pass
|
||||
if not (screen_w):
|
||||
hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string, hp_clear_screen, hp_pause = None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None
|
||||
try:
|
||||
import sys
|
||||
try:
|
||||
t_nw = sys.platform == "numworks"
|
||||
if sys.platform == "nspire" or t_nw:
|
||||
try: # KhiCAS Micropython
|
||||
import graphic, nsp, cas, time
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
graphic.draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, color_bits, 1))
|
||||
def poly_fill_rect(x1, y1, x2, y2, c):
|
||||
graphic.draw_filled_rectangle(int(x1), int(y1), int(x2), int(y2), c)
|
||||
def poly_draw_circle(x, y, r, c):
|
||||
graphic.draw_circle(int(x), int(y), int(r), c)
|
||||
def poly_fill_circle(x, y, r, c):
|
||||
graphic.draw_filled_circle(int(x), int(y), int(r), c)
|
||||
def poly_draw_ellipse(x, y, rx, ry, c):
|
||||
graphic.draw_arc(int(x), int(y), int(rx), int(ry), 0, 360, c)
|
||||
def poly_fill_ellipse(x, y, rx, ry, c):
|
||||
graphic.draw_filled_arc(int(x), int(y), int(rx), int(ry), 0, 360, c)
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
cas.caseval('draw_string("' + s + '", ' + str(float(x)) + ', ' + str(float(y)) + ', ' + str(col3_2_rgb(cf, color_bits, 1)) + ', ' + str(col3_2_rgb(cb, color_bits, 1)) + ')')
|
||||
def poly_wait_key():
|
||||
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:4, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41, KEY_0:48, KEY_1:49, KEY_2:50, KEY_3:51, KEY_4:52, KEY_5:53, KEY_6:54, KEY_7:55, KEY_8:56, KEY_9:57}
|
||||
key = int(cas.caseval("get_key()"))
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
def poly_monotonic():
|
||||
return time.monotonic() / (1 + t_nw*999)
|
||||
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_show, poly_pause, need_clear, need_line, need_rect, need_ellipse, need_string, need_monotonic, screen_need_clear_on_init = 320, 222, 15, 18, graphic.get_pixel, graphic.set_pixel, graphic.show_screen, nsp.waitKeypress, 1, 0, 0, 0, 0, 0, 1
|
||||
font_num_w = font_w
|
||||
except: # Nspire MicroPython
|
||||
import nsp
|
||||
screen_w, screen_h, need_clear, show_need_pause_on_exit = 320, 240, 1, 1
|
||||
tcanvas = nsp.Texture(screen_w, screen_h, 0)
|
||||
poly_get_pixel = tcanvas.getPx
|
||||
def poly_set_pixel(x, y, c):
|
||||
if x>=0 and x<=screen_w-1 and y>=0 and y <=screen_h-1:
|
||||
tcanvas.setPx(x, y, col3_2_rgb(c, color_bits, 1))
|
||||
poly_show, poly_pause = tcanvas.display, nsp.waitKeypress
|
||||
elif sys.platform == "TI-Nspire": # CX II
|
||||
import time, ti_system
|
||||
screen_w, screen_h, font_w, font_h, need_monotonic, need_sleep, poly_sleep = 318, 212, 12, 12, 0, 0, time.sleep
|
||||
font_num_w = font_w
|
||||
def test(d,f):
|
||||
t=f()
|
||||
time.sleep(d)
|
||||
return round((f()-t)/d,0)
|
||||
if test(0.1, time.clock) == 1:
|
||||
poly_monotonic = time.clock
|
||||
else:
|
||||
poly_monotonic = time.time
|
||||
d_key = {KEY_LEFT:'left', KEY_UP:'up', KEY_DOWN:'down', KEY_RIGHT:'right', KEY_ENTER:'enter', KEY_ESC:'esc', KEY_LEFT_PARENTHESIS:'(', KEY_RIGHT_PARENTHESIS:')', KEY_0:'0', KEY_1:'1', KEY_2:'2', KEY_3:'3', KEY_4:'4', KEY_5:'5', KEY_6:'6', KEY_7:'7', KEY_8:'8', KEY_9:'9'}
|
||||
def poly_get_key():
|
||||
key = ti_system.get_key()
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
def poly_wait_key():
|
||||
key = ""
|
||||
while key == "":
|
||||
key = ti_system.get_key()
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
def poly_test_key(v):
|
||||
return poly_get_key() == d_key[v]
|
||||
def poly_esc_key():
|
||||
return poly_test_key(KEY_ESC)
|
||||
if "gp" in keys:
|
||||
import ti_image
|
||||
need_line, need_rect, need_ellipse, need_string = 1, 1, 1, 1
|
||||
tcanvas = ti_image.new_image(screen_w, screen_h, (255,255,255))
|
||||
poly_get_pixel, poly_set_pixel = tcanvas.get_pixel, tcanvas.set_pixel
|
||||
def poly_show():
|
||||
tcanvas.show_image(0,0)
|
||||
else:
|
||||
import ti_draw
|
||||
ti_draw.use_buffer()
|
||||
ti_draw.set_pen("thin","solid")
|
||||
need_line, need_rect, need_ellipse, need_string, poly_show, set_buffer = 0, 0, 0, 0, ti_draw.paint_buffer, ti_draw.use_buffer
|
||||
def poly_set_pixel(x, y, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.plot_xy(x, y, 7)
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.draw_line(x1, y1, x2, y2)
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.fill_rect(x, y, w, h)
|
||||
def poly_draw_circle(x, y, r, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.draw_circle(x, y, r)
|
||||
def poly_fill_circle(x, y, r, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.fill_circle(x, y, r)
|
||||
def poly_draw_ellipse(x, y, rx, ry, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
x0, y0 = x - rx, y - ry
|
||||
for dy in range(1 + (y0 > int(y0))):
|
||||
for dx in range(1 + (x0 > int(x0))):
|
||||
ti_draw.draw_arc(x0 + dx, y0 + dy, 2 * rx, 2 * ry, 0, 360)
|
||||
def poly_fill_ellipse(x, y, rx, ry, c):
|
||||
ti_draw.set_color(tuple(c))
|
||||
ti_draw.fill_arc(x - rx, y - ry, 2 * rx, 2 * ry, 0, 360)
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
|
||||
ti_draw.set_color(tuple(cf))
|
||||
ti_draw.draw_text(x, y + font_h, s)
|
||||
elif sys.platform.startswith('TI-Python'):
|
||||
import ti_graphics, ti_system, time
|
||||
screen_w, screen_h, font_w, font_h, screen_y0, need_line, need_rect, need_ellipse, need_string, need_monotonic, need_sleep, poly_pause, poly_wait_key, poly_sleep, poly_monotonic, poly_esc_key, need_clear, show_need_pause_on_exit, need_sleep, screen_need_clear_on_init = 320, 210, 10, 15, 30, 0, 0, 0, 0, 0, ti_system.disp_wait, ti_system.wait_key, time.sleep, time.monotonic, ti_system.escape, 1, 1, 0, 1
|
||||
font_num_w = font_w
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
ti_graphics.setColor(c)
|
||||
ti_graphics.drawLine(x1, y1 + screen_y0, x2, y2 + screen_y0)
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
ti_graphics.setColor(c)
|
||||
ti_graphics.fillRect(x, y + screen_y0, w, h)
|
||||
def poly_get_pixel(x, y):
|
||||
return ti_graphics.getPixel(x, y + screen_y0)
|
||||
def poly_set_pixel(x, y, c):
|
||||
ti_graphics.setPixel(x, y + screen_y0, c)
|
||||
def poly_draw_ellipse(x, y, rx, ry, c):
|
||||
ti_graphics.setColor(c)
|
||||
x0, y0 = x - rx, y - ry
|
||||
for dy in range(1 + (y0 > int(y0))):
|
||||
for dx in range(1 + (x0 > int(x0))):
|
||||
ti_graphics.drawArc(x0 + dx, y0 + dy + screen_y0, 2 * rx, 2 * ry, 0, 3600)
|
||||
def poly_fill_ellipse(x, y, rx, ry, c):
|
||||
ti_graphics.setColor(c)
|
||||
ti_graphics.fillArc(x - rx, y - ry + screen_y0, 2 * rx, 2 * ry, 0, 3600)
|
||||
def poly_draw_circle(x, y, r, c):
|
||||
poly_draw_ellipse(x, y, r, r, c)
|
||||
def poly_fill_circle(x, y, r, c):
|
||||
ti_graphics.setColor(c)
|
||||
ti_graphics.fillCircle(x, y + screen_y0, r)
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
|
||||
ti_graphics.setColor(cf)
|
||||
ti_graphics.drawString(s, x, y + screen_y0)
|
||||
def poly_wait_key():
|
||||
d_key = {KEY_LEFT:2, KEY_UP:3, KEY_DOWN:4, KEY_RIGHT:1, KEY_ENTER:5, KEY_ESC:9, KEY_LEFT_PARENTHESIS:133, KEY_RIGHT_PARENTHESIS:134, KEY_0:142, KEY_1:143, KEY_2:144, KEY_3:145, KEY_4:146, KEY_5:147, KEY_6:148, KEY_7:149, KEY_8:150, KEY_9:151}
|
||||
key = ti_system.wait_key()
|
||||
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
|
||||
except: # Graph 35+E/USB / 75/85/95
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
if not (screen_w): # Casio Graph 90/35+E II
|
||||
try:
|
||||
import casioplot
|
||||
casioplot.set_pixel(0, 0, (0, 0, 255))
|
||||
col = casioplot.get_pixel(0, 0)
|
||||
t = col[0] == col[2]
|
||||
screen_w, screen_h, poly_has_color, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_show, poly_clear_screen, need_string, has_keys = t and 128 or 384, t and 64 or 192, not (t), t and 6 or 10, t and 5 or 10, casioplot.get_pixel, casioplot.set_pixel, casioplot.show_screen, casioplot.clear_screen, 0, 0
|
||||
font_num_w = t and 4 or 8
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
|
||||
casioplot.draw_string(x, y, s, cf, "small")
|
||||
def poly_pause():
|
||||
try:
|
||||
while(1):
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
if not (screen_w):
|
||||
try: # NumWorks
|
||||
import kandinsky, ion, time
|
||||
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_draw_string, poly_sleep, poly_monotonic, need_rect, need_string, need_monotonic, need_sleep = 320, 222, 11, 18, kandinsky.get_pixel, kandinsky.set_pixel, kandinsky.draw_string, time.sleep, time.monotonic, 0, 0, 0, 0
|
||||
font_num_w = font_w
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
kandinsky.fill_rect(int(x), int(y), int(w), int(h), c)
|
||||
def poly_pause():
|
||||
def key_down():
|
||||
for k in range(53):
|
||||
if ion.keydown(k):
|
||||
return 1
|
||||
return 0
|
||||
while key_down():
|
||||
pass
|
||||
while not (key_down()):
|
||||
pass
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
kandinsky.draw_string(s, x, y, cf, cb)
|
||||
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_RIGHT:2, KEY_DOWN:3, KEY_ENTER:52, KEY_ESC:5, KEY_LEFT_PARENTHESIS:33, KEY_RIGHT_PARENTHESIS:34, KEY_0:48, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:36, KEY_5:37, KEY_6:38, KEY_7:30, KEY_8:31, KEY_9:32}
|
||||
def poly_get_key():
|
||||
for k in d_key:
|
||||
if poly_test_key(d_key[k]):
|
||||
return k
|
||||
return 0
|
||||
def poly_wait_key():
|
||||
k = 0
|
||||
while not k:
|
||||
k = poly_get_key()
|
||||
return k
|
||||
def poly_test_key(v):
|
||||
return ion.keydown(d_key[v])
|
||||
def poly_esc_key():
|
||||
return poly_test_key(KEY_ESC)
|
||||
except:
|
||||
try: # HP Prime
|
||||
import hpprime
|
||||
screen_w, screen_h, font_h, color_bits, need_clear, show_need_pause_on_exit, screen_need_clear_on_init, need_line, need_rect, need_string = 320, 240, 15, (8, 8, 8), 1, 1, 1, 0, 0, 0
|
||||
hpprime.dimgrob(1, screen_w, screen_h, 0)
|
||||
def poly_set_pixel(x, y, c):
|
||||
hpprime.pixon(1, x, y, col3_2_rgb(c, color_bits, 1))
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
hpprime.line(1, x1, y1, x2, y2, col3_2_rgb(c, color_bits, 1))
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
hpprime.fillrect(1, x, y, w, h, col3_2_rgb(c, color_bits, 1), col3_2_rgb(c, color_bits, 1))
|
||||
def poly_show():
|
||||
hpprime.strblit(0, 0, 0, screen_w, screen_h, 1)
|
||||
def poly_pause():
|
||||
while hpprime.keyboard(): pass
|
||||
while not(hpprime.keyboard()): pass
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
sz = hpprime.eval('TEXTSIZE("'+s+'")')
|
||||
poly_fill_rect(x, y, sz[0], sz[1], cb)
|
||||
hpprime.textout(1, x, y, s, col3_2_rgb(cf, color_bits, 1))
|
||||
d_key = {KEY_LEFT:7, KEY_UP:2, KEY_DOWN:12, KEY_RIGHT:8, KEY_ENTER:30, KEY_ESC:4, KEY_LEFT_PARENTHESIS:28, KEY_RIGHT_PARENTHESIS:28, KEY_0:47, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:37, KEY_5:38, KEY_6:39, KEY_7:32, KEY_8:33, KEY_9:34 }
|
||||
def poly_get_key():
|
||||
for k in d_key:
|
||||
if poly_test_key(k):
|
||||
return k
|
||||
return 0
|
||||
def poly_wait_key():
|
||||
while not hpprime.keyboard(): pass
|
||||
return poly_get_key()
|
||||
def poly_wait_release():
|
||||
while hpprime.keyboard(): pass
|
||||
def poly_test_key(v):
|
||||
return hpprime.keyboard() & (1 << d_key[v])
|
||||
def poly_esc_key():
|
||||
return poly_test_key(KEY_ESC)
|
||||
except:
|
||||
pass
|
||||
|
||||
if screen_w:
|
||||
if need_line:
|
||||
def poly_draw_line(x1, y1, x2, y2, c):
|
||||
m, a1, b1, a2, b2 = 0, int(x1), int(y1), int(x2), int(y2)
|
||||
if (x2 - x1) ** 2 < (y2 - y1) ** 2:
|
||||
m, a1, a2, b1, b2 = 1, b1, b2, a1, a2
|
||||
if min(a1, a2) != a1: a1, b1, a2, b2 = a2, b2, a1, b1
|
||||
for a in range(a1, a2 + 1):
|
||||
b = int(b1 + (b2 - b1) * (a - a1) / ((a2 - a1) or 1))
|
||||
poly_set_pixel((a, b)[m], (b, a)[m], c)
|
||||
|
||||
if need_rect:
|
||||
def poly_fill_rect(x, y, w, h, c):
|
||||
for k in range(h):
|
||||
poly_draw_line(x, y + k, x + w - 1, y + k, c)
|
||||
|
||||
if need_ellipse:
|
||||
from math import sqrt
|
||||
def poly_draw_ellipse(x, y, rx, ry, c):
|
||||
for h in range(-int(ry), int(ry)+1):
|
||||
w = sqrt(max(0, rx*rx*(1-h*h/ry/ry)))
|
||||
x1, x2 = int(x - w), int(x + w)
|
||||
yc = int(y + h)
|
||||
poly_set_pixel(x1, yc, c)
|
||||
poly_set_pixel(x2, yc, c)
|
||||
for w in range(-int(rx), int(rx)+1):
|
||||
h = sqrt(max(0, ry*ry*(1-w*w/rx/rx)))
|
||||
y1, y2 = int(y - h), int(y + h)
|
||||
xc = int(x + w)
|
||||
poly_set_pixel(xc, y1, c)
|
||||
poly_set_pixel(xc, y2, c)
|
||||
|
||||
def poly_fill_ellipse(x, y, rx, ry, c):
|
||||
for h in range(-int(ry), int(ry)+1):
|
||||
w = sqrt(max(0, rx*rx*(1-h*h/ry/ry)))
|
||||
poly_fill_rect(int(x - w), int(y + h), int(2 * w), 1, c)
|
||||
def poly_draw_circle(x, y, r, c):
|
||||
poly_draw_ellipse(x, y, r, r, c)
|
||||
def poly_fill_circle(x, y, r, c):
|
||||
poly_fill_ellipse(x, y, r, r, c)
|
||||
|
||||
if need_string:
|
||||
from polyfont import poly_font
|
||||
font_w, font_h = 11, 10
|
||||
font_num_w = 9
|
||||
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
|
||||
for c in s:
|
||||
c = ord(c) >= 33 and ord(c) <= 127 and ord(c) - 32 or 0
|
||||
poly_fill_rect(x, y, font_w, font_h, cb)
|
||||
for v in (0,) + poly_font[c] + (0,):
|
||||
ty = y
|
||||
while v:
|
||||
if v & 1:
|
||||
poly_set_pixel(x, ty, cf)
|
||||
ty += 1
|
||||
v //= 2
|
||||
x += 1
|
||||
|
||||
if need_clear:
|
||||
def poly_clear_screen():
|
||||
poly_fill_rect(0, 0, screen_w, screen_h, [255, 255, 255])
|
||||
|
||||
if screen_need_clear_on_init:
|
||||
poly_clear_screen_init = poly_clear_screen
|
||||
else:
|
||||
poly_clear_screen_init = fnop
|
||||
|
||||
if need_sleep:
|
||||
def poly_sleep(d):
|
||||
if need_monotonic:
|
||||
for k in range(int(d*1000)):
|
||||
pass
|
||||
else:
|
||||
s = poly_monotonic() + d
|
||||
while poly_monotonic() < s:
|
||||
pass
|
||||
|
||||
if show_need_pause_on_exit:
|
||||
def poly_show_exit():
|
||||
poly_show()
|
||||
poly_pause()
|
||||
else:
|
||||
poly_show_exit = poly_show
|
||||
|
||||
l = []
|
||||
for k in keys:
|
||||
if k=="w":
|
||||
l.append(screen_w)
|
||||
if k=="h":
|
||||
l.append(screen_h)
|
||||
if k=="hc":
|
||||
l.append(poly_has_color)
|
||||
if k=="fw":
|
||||
l.append(font_w)
|
||||
if k=="fwn":
|
||||
l.append(font_num_w)
|
||||
if k=="fh":
|
||||
l.append(font_h)
|
||||
if k=="gp":
|
||||
l.append(poly_get_pixel)
|
||||
if k=="sp":
|
||||
l.append(poly_set_pixel)
|
||||
if k=="dl":
|
||||
l.append(poly_draw_line)
|
||||
if k=="fr":
|
||||
l.append(poly_fill_rect)
|
||||
if k=="dc":
|
||||
l.append(poly_draw_circle)
|
||||
if k=="fc":
|
||||
l.append(poly_fill_circle)
|
||||
if k=="de":
|
||||
l.append(poly_draw_ellipse)
|
||||
if k=="fe":
|
||||
l.append(poly_fill_ellipse)
|
||||
if k=="ds":
|
||||
l.append(poly_draw_string)
|
||||
if k=="cl":
|
||||
l.append(poly_clear_screen)
|
||||
if k=="cli":
|
||||
l.append(poly_clear_screen_init)
|
||||
if k=="sh":
|
||||
l.append(poly_show)
|
||||
if k=="she":
|
||||
l.append(poly_show_exit)
|
||||
if k=="p":
|
||||
l.append(poly_pause)
|
||||
if k=="sb":
|
||||
l.append(poly_set_buffer)
|
||||
if k=="m":
|
||||
l.append(poly_monotonic)
|
||||
if k=="s":
|
||||
l.append(poly_sleep)
|
||||
if k=="ek":
|
||||
l.append(poly_esc_key)
|
||||
if k=="gk":
|
||||
l.append(poly_get_key)
|
||||
if k=="wk":
|
||||
l.append(poly_wait_key)
|
||||
if k=="wr":
|
||||
l.append(poly_wait_release)
|
||||
if k=="tk":
|
||||
l.append(poly_test_key)
|
||||
if k=="hk":
|
||||
l.append(has_keys)
|
||||
return l
|