Difference between revisions of "API"
(39 intermediate revisions by 5 users not shown) | |||
Line 7: | Line 7: | ||
==WOWCube Paradigms== | ==WOWCube Paradigms== | ||
− | + | WOWCube executes 8 copies of the byte-code of the script at the same time, providing functions for the interaction of scripts with each other, drawing functions, functions for accessing resources, and other specific functions. Each copy of the script has access to 3 displays. Resource scripts are packed into a package. | |
− | ==Graphic functions== | + | ==Pawn API== |
+ | ===Graphic functions=== | ||
− | G2D acceleration | + | ====Graphics 2D acceleration (G2D)==== |
− | + | WOWCube provides the 2D acceleration interfaces to enhance gaming experience . Basically G2D engine allows to blend up to the 4 image layers at once with a HW acceleration. However there is no limit of layers, they are blended in a cascade. For example, if Pawn script requested 7 layers to be blended then 2 HW blending will occur: | |
− | + | [[File:Cascade.png|center|G2D cascading scheme]] | |
− | + | Result of the blending can be saved as an internal G2D resource or flushed immediately on the specified display. Internal G2D resources can be used as an usual bitmap primitive ([[API#abi_CMD_BITMAP|abi_CMD_BITMAP]]) or reused as an input for the next G2D action. | |
+ | Basic coordinate principle: | ||
+ | [[File:G2d_coordinates.png|center|G2D coordinates sceme]] | ||
+ | Coordinates are limited from -2048 to 2047. Maximum layers size is 240x240. | ||
− | [[ | + | =====abi_CMD_G2D_BEGIN_BITMAP===== |
+ | Syntax: | ||
+ | abi_CMD_G2D_BEGIN_BITMAP(const resID, const width, const height, const bool:replace) | ||
+ | Description: | ||
+ | : abi_CMD_G2D_BEGIN_BITMAP and [[API#abi_CMD_G2D_END|abi_CMD_G2D_END]] delimits the group of layers to be blended into internal G2D resource. This API is not intended for frequent usage. It is better suited for complex background generation on game initialization or dynamic resource modification triggered by rare game events. | ||
+ | Arguments: | ||
+ | : ''resID'' | ||
+ | :: ID of the resource that will be generated from blending layers presented between abi_CMD_G2D_BEGIN_BITMAP and the subsequent [[API#abi_CMD_G2D_END|abi_CMD_G2D_END]]. G2D engine can keep up to 3 different resources with IDs: 0, 1 and 2. | ||
+ | : ''width'' | ||
+ | :: Width of the resulting resource. G2D engine can keep resource of 240px width maximum. | ||
+ | : ''height'' | ||
+ | :: Height of the resulting resource. G2D engine can keep resource of 240px height maximum. | ||
+ | : ''replace'' | ||
+ | :: If true, then an existing image will be replaced completely, otherwise it will be overwritten by reusing itself as a background layer. | ||
− | === | + | =====abi_CMD_G2D_BEGIN_DISPLAY===== |
+ | Syntax: | ||
+ | abi_CMD_G2D_BEGIN_DISPLAY(const display, const bool:replace) | ||
+ | Description: | ||
+ | : abi_CMD_G2D_BEGIN_DISPLAY and [[API#abi_CMD_G2D_END|abi_CMD_G2D_END]] delimits the group of layers to be blended directly into display framebuffer. Obviously this API is designed for rendering scene on game tick. This API is not limited by layers count as well as [[API#abi_CMD_G2D_BEGIN_BITMAP|abi_CMD_G2D_BEGIN_BITMAP]]. However it is strictly recommended to blend no more than 4 layers. Otherwise cascade blending will be initiated resulting in some FPS drop. | ||
+ | Arguments: | ||
+ | : ''display'' | ||
+ | :: ID of the display which framebuffer will be used for blending. Each module have 3 displays with ID starting from 0. | ||
+ | : ''replace'' | ||
+ | :: If true then an existing image will be replaced completely, otherwise it will be overwritten by reusing itself as a background layer. | ||
− | === | + | =====abi_CMD_G2D_ADD_SPRITE===== |
+ | Syntax: | ||
+ | abi_CMD_G2D_ADD_SPRITE(const resID, const bool:g2d, const x, const y, const alpha, const color, const rotation, const mirror) | ||
+ | Description: | ||
+ | : Specifies game resource which will be used as a layer for blending. | ||
+ | Arguments: | ||
+ | : ''resID'' | ||
+ | :: ID of the resource to be uses as a layer. | ||
+ | : ''g2d'' | ||
+ | :: Indicates if an internal G2D resource is specified or not. | ||
+ | : ''x'', ''y'' | ||
+ | :: Coordinates of the bitmap center to place on the layer. | ||
+ | : ''alpha'' | ||
+ | :: Layer transparency in range between 0x00 and 0xFF, where 0x00 is a fully transparent layer. | ||
+ | : ''color'' | ||
+ | :: Layer's source key - a color in ARGB8888 format to be avoided. | ||
+ | : ''rotation'' | ||
+ | :: Clockwise rotation angle in degrees. It is possible to specify free angle, but only right angles have HW acceleration. Currently rotation only applicable for external resources. | ||
+ | : ''mirror'' | ||
+ | :: Mirroring variant. Possible values are self-explained: MIRROR_BLANK, MIRROR_X, MIRROR_Y, MIRROR_XY. | ||
+ | =====abi_CMD_G2D_ADD_RECTANGLE===== | ||
+ | Syntax: | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(const x, const y, const width, const height, const color) | ||
+ | Description: | ||
+ | : Specifies rectangle area which will be used as layer of blending. This API is not intended for frequent usage, i.e. particles generation. It is better suited for changing image background or applying color mask. | ||
+ | Arguments: | ||
+ | : ''x'', ''y'' | ||
+ | :: Coordinates of top left rectangle corner. | ||
+ | : ''width'' | ||
+ | :: Rectangle width. | ||
+ | : ''height'' | ||
+ | :: Rectangle height. | ||
+ | : ''color'' | ||
+ | :: Rectangle color in ARGB8888 format. | ||
− | Example | + | =====abi_CMD_G2D_END===== |
+ | Syntax: | ||
+ | abi_CMD_G2D_END() | ||
+ | Description: | ||
+ | : abi_CMD_G2D_END() and [[API#abi_CMD_G2D_BEGIN_BITMAP|abi_CMD_G2D_BEGIN_BITMAP]]/[[API#abi_CMD_G2D_BEGIN_DISPLAY|abi_CMD_G2D_BEGIN_DISPLAY]] delimits the group of layers to be blended. After abi_CMD_G2D_END call final blending will be initiated and results will be stored according to the begin comand. | ||
+ | |||
+ | =====Examples===== | ||
+ | 1. Render into inner G2D resource buffer #face and display it on the display #face. Please, note that last argument of abi_CMD_BITMAP is a `true` flag, which means G2D resource should be used: | ||
+ | ... | ||
+ | abi_CMD_G2D_BEGIN_BITMAP(face, 240, 240, true); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize0, 120 - animationSquareSize0, animationSquareSize0 * 2, animationSquareSize0 * 2, 0xdfff0000); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize1, 120 - animationSquareSize1, animationSquareSize1 * 2, animationSquareSize1 * 2, 0xdfffff00); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize2, 120 - animationSquareSize2, animationSquareSize2 * 2, animationSquareSize2 * 2, 0xdfff00ff); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize3, 120 - animationSquareSize3, animationSquareSize3 * 2, animationSquareSize3 * 2, 0xdf00ffff); | ||
+ | abi_CMD_G2D_ADD_SPRITE(resID, false, 120, 120, animationAlpha, 0x00000000, animationAngle, MIRROR_BLANK); | ||
+ | abi_CMD_G2D_END(); | ||
+ | ... | ||
+ | abi_CMD_BITMAP(face, 120, 120, 0, MIRROR_BLANK, true); | ||
+ | ... | ||
+ | abi_CMD_REDRAW(face); | ||
+ | ... | ||
+ | 2. Render directly into display framebuffer #face. This will produce same result on display as example #1, but the generated image is not saved: | ||
+ | ... | ||
+ | abi_CMD_G2D_BEGIN_DISPLAY(face, true); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize0, 120 - animationSquareSize0, animationSquareSize0 * 2, animationSquareSize0 * 2, 0xdfff0000); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize1, 120 - animationSquareSize1, animationSquareSize1 * 2, animationSquareSize1 * 2, 0xdfffff00); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize2, 120 - animationSquareSize2, animationSquareSize2 * 2, animationSquareSize2 * 2, 0xdfff00ff); | ||
+ | abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize3, 120 - animationSquareSize3, animationSquareSize3 * 2, animationSquareSize3 * 2, 0xdf00ffff); | ||
+ | abi_CMD_G2D_ADD_SPRITE(resID, false, 120, 120, animationAlpha, 0x00000000, animationAngle, MIRROR_BLANK); | ||
+ | abi_CMD_G2D_END(); | ||
+ | ... | ||
+ | |||
+ | ====Font drawing functions==== | ||
+ | =====abi_CMD_TEXT===== | ||
+ | API: | ||
+ | abi_CMD_TEXT(const text[], const fontResID, const x, const y, const scale, const angle, const r, const g, const b) | ||
+ | Description: | ||
+ | : Intended to render a system font or a custom font from resources with specified coordinates, scale and rotation at an arbitrary angle. | ||
+ | Arguments: | ||
+ | : ''text'' | ||
+ | :: Array of chars. | ||
+ | : ''fontResID'' | ||
+ | :: Custom font resource identifier. Provide ''-1'' to use system font resource. | ||
+ | : ''x'', ''y'' | ||
+ | :: Coordinates of top left rectangle corner. | ||
+ | : ''scale'', ''angle'' | ||
+ | :: Percentage scale and clockwise rotation angle in degrees. Max size of font is 200x200 px. (scale = 100%) | ||
+ | : ''r'', ''g'', ''b'' | ||
+ | :: Font color in RGB format. | ||
+ | |||
+ | Example: | ||
new text[4] = ['A', 'p', 'p', '\0']; | new text[4] = ['A', 'p', 'p', '\0']; | ||
− | abi_CMD_TEXT(text, 90, 160, | + | abi_CMD_TEXT(text, RES_ID_FONT, 90, 160, 16, current_angles[face], 255, 0, 0); |
+ | |||
+ | ====TEXTURE drawing functions==== | ||
+ | =====abi_CMD_DYNAMIC_TEXTURE===== | ||
+ | |||
+ | API: | ||
+ | |||
+ | abi_CMD_DYNAMIC_TEXTURE(const effectId = 1, const time = any value, const args[] = {0x04030201, 0x08070605, 0x00000A09}, const argsCount = 3, const bool:g2d = false) | ||
+ | |||
+ | Description: | ||
+ | : Render a texture with chosen algorithm and parameters. | ||
+ | Arguments: | ||
+ | : ''effectId'' | ||
+ | :: Define algorithm to render texture. | ||
+ | :: Available values : G2D_DYNAMIC_TEXTURE_MOSAIC | ||
+ | |||
+ | : ''time '' | ||
+ | :: Current time value. Use any fixed value to static texture or set current time value in milliseconds to make texture alive. | ||
+ | : ''args'', ''argsCount'' | ||
+ | :: Byte stream of algorithm settings it's aligned to 4 bytes, because of pawn supports only 32-bit values. | ||
+ | :: Size of array depends on algorithm. For example mosaic algorithm has size of settings equals 10 bytes , so we must use aligned 4 bytes - 12 bytes array and argsCount = 3 | ||
+ | |||
+ | : ''g2d'' | ||
+ | :: false - Use pawn default buffer to draw texture. | ||
+ | :: true - Use g2d buffer to draw texture - not supported now. | ||
+ | |||
+ | '''G2D_DYNAMIC_TEXTURE_MOSAIC''' alogrithm description | ||
+ | |||
+ | :So in effect named 'mosaic' we have settings of 10 parameters each one 1 byte | ||
+ | |||
+ | :Noise factors : | ||
+ | ::factor x : values from 0 to 10 | ||
+ | ::factor y : values from 0 to 10 | ||
+ | ::factor xy : values from 0 to 10 | ||
+ | :Time factors : | ||
+ | ::factor x : values from 0 to 10 | ||
+ | ::factor y : values from 0 to 10 | ||
+ | ::factor xy : values from 0 to 10 | ||
+ | :Color factors : | ||
+ | ::r : values from 0 to 10 | ||
+ | ::g : values from 0 to 10 | ||
+ | ::b : values from 0 to 10 | ||
+ | :Zoom factor : | ||
+ | ::zoom values from 0 to 10 | ||
+ | |||
+ | For example we want to set all parameters above with values in order 1,2,3,4,5,6,7,8,9,10. Take in attention that each parameter is 1 byte we must make array of 32-bit values | ||
+ | 0x04030201, 0x08070605, 0x00000A09 | ||
+ | |||
+ | Example: | ||
+ | mosaic_effect_settings = { 0x04030201, 0x08070605, 0x00000A09 }; | ||
+ | mosaic_effect_settings_length = 3; | ||
+ | abi_CMD_DYNAMIC_TEXTURE(G2D_DYNAMIC_TEXTURE_MOSAIC , currentTime, mosaic_effect_settings, mosaic_effect_settings_length); | ||
+ | |||
+ | ===Motion sensors=== | ||
+ | ====abi_MTD_GetFaceAccel(X/Y/Z)==== | ||
+ | Syntax: | ||
+ | abi_MTD_GetFaceAccelX(const faceN) | ||
+ | abi_MTD_GetFaceAccelY(const faceN) | ||
+ | abi_MTD_GetFaceAccelZ(const faceN) | ||
+ | Description: | ||
+ | : Get the value of acceleration along the requested axis. | ||
+ | Arguments | ||
+ | : ''faceN'' | ||
+ | :: Number of the module face for which requested axis is belong. | ||
+ | |||
+ | ====abi_MTD_GetFaceGyro(X/Y/Z)==== | ||
+ | Syntax: | ||
+ | abi_MTD_GetFaceGyroX(const faceN) | ||
+ | abi_MTD_GetFaceGyroY(const faceN) | ||
+ | abi_MTD_GetFaceGyroZ(const faceN) | ||
+ | Description: | ||
+ | : Get the gyro value around the requested axis. | ||
+ | Arguments | ||
+ | : ''faceN'' | ||
+ | :: Number of the module face for which requested axis is belong. | ||
+ | |||
+ | ====abi_MTD_GetTapFace==== | ||
+ | Syntax: | ||
+ | abi_MTD_GetTapFace() | ||
+ | Description: | ||
+ | : Get the face ID which was tapped. ID is not a face number which is used for drawing in abi_CMD_G2D_BEGIN_DISPLAY or abi_CMD_REDRAW, but that number can be calculated by subtracting by one from ID value. See possible values below. | ||
+ | Return values: | ||
+ | : ''MTD_TAP_DIRECTION_NONE = 0'' | ||
+ | :: Indicates that the module wan not tapped. | ||
+ | : ''MTD_TAP_DIRECTION_X = 1'' | ||
+ | : ''MTD_TAP_DIRECTION_Y = 2'' | ||
+ | : ''MTD_TAP_DIRECTION_Z = 3'' | ||
+ | :: Indicated direction of tap. | ||
+ | |||
+ | ====abi_MTD_IsTapOpposite==== | ||
+ | Syntax: | ||
+ | abi_MTD_IsTapOpposite() | ||
+ | Description: | ||
+ | : Get the flag if the tap was detected in opposite direction. | ||
+ | |||
+ | ====abi_MTD_GetTapsCount==== | ||
+ | Syntax: | ||
+ | abi_MTD_GetTapsCount() | ||
+ | Description: | ||
+ | : Get the count of subsequent taps. Tap is treated as a subsequent if it was detected within predefined interval (350ms). Count will be zero until sequence is finished, i.e. next tap is not detected within interval. | ||
+ | |||
+ | ====abi_checkShake==== | ||
+ | Syntax: | ||
+ | abi_checkShake() | ||
+ | Description: | ||
+ | : Checks if the number of shakes of the cube was more than a certain threshold then exits the script | ||
+ | |||
+ | |||
+ | ====Examples==== | ||
+ | 1. Flash the face on which tap was detected. Print an ID of that face. Color of the flash depends on taps count: red - one tap, green - two taps and blue - three. | ||
+ | new delay = 0; | ||
+ | new color = 0x000000; | ||
+ | ONTICK() { | ||
+ | if (!color) { | ||
+ | switch (abi_MTD_GetTapsCount()) { | ||
+ | case 1: | ||
+ | color = 0xff0000; | ||
+ | case 2: | ||
+ | color = 0x00ff00; | ||
+ | case 3: | ||
+ | color = 0x0000ff; | ||
+ | } | ||
+ | } | ||
+ | if (delay % 25 == 0) { | ||
+ | for (new i = 0; i < FACES_MAX; i++) { | ||
+ | if (i == (abi_MTD_GetTapFace() - 1)) { | ||
+ | abi_CMD_FILL_2(color); | ||
+ | color = 0x000000; | ||
+ | switch (abi_MTD_GetTapFace()) { | ||
+ | case 1: | ||
+ | abi_CMD_TEXT(['1', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); | ||
+ | case 2: | ||
+ | abi_CMD_TEXT(['2', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); | ||
+ | case 3: | ||
+ | abi_CMD_TEXT(['3', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); | ||
+ | } | ||
+ | } else { | ||
+ | abi_CMD_FILL(0, 0, 0); | ||
+ | } | ||
+ | abi_CMD_REDRAW(i); | ||
+ | } | ||
+ | } | ||
+ | delay++; | ||
+ | } | ||
+ | 2. Exit from script | ||
+ | ONTICK() { | ||
+ | if (abi_cubeN == 0) { | ||
+ | abi_checkShake(); | ||
+ | } | ||
+ | // Script logic | ||
+ | } | ||
+ | |||
+ | ===Save/load functions=== | ||
+ | |||
+ | ====abi_CMD_SAVE_STATE==== | ||
+ | Syntax: | ||
+ | bool:abi_CMD_SAVE_STATE(const data[], size = sizeof(data)) | ||
+ | Description: | ||
+ | : Save maximum 256 bytes of data to wowcube flash memory. | ||
+ | Arguments | ||
+ | : ''data'' | ||
+ | :: Game data to save. | ||
+ | : ''size'' | ||
+ | :: Size of game data. | ||
+ | Return values: | ||
+ | : ''return false'' | ||
+ | :: If size is bigger then 256 bytes. | ||
+ | |||
+ | ====abi_CMD_LOAD_STATE==== | ||
+ | Syntax: | ||
+ | abi_CMD_LOAD_STATE() | ||
+ | Description: | ||
+ | : Sends a command requesting the platform to load script data. The response from the platform is not instantaneous and takes several milliseconds. | ||
+ | |||
+ | ====Examples==== | ||
+ | 1. Load data at the start. | ||
+ | // This function is called when a response is received from the platform | ||
+ | ON_LOAD_GAME_DATA (const pkt[]) { | ||
+ | // Deserialize pkt | ||
+ | currentLevelNumber = pkt[1]; // Starting with 1 cause 0 pkt element holding command ID | ||
+ | score = pkt[2]; | ||
+ | moves = pkt[3]; | ||
+ | ... | ||
+ | record = pkt[GAME_SAVE_SIZE]; | ||
+ | } | ||
+ | ON_INIT () { | ||
+ | abi_CMD_LOAD_STATE (); | ||
+ | } | ||
+ | |||
+ | 2. Save the data after the end of the level. | ||
+ | SaveGameState () { | ||
+ | new saveData [GAME_SAVE_SIZE]; | ||
+ | // Assign all necessary data | ||
+ | saveData[0] = currentLevelNumber; | ||
+ | saveData[1] = score; | ||
+ | saveData[2] = moves; | ||
+ | ... | ||
+ | saveData[GAME_SAVE_SIZE - 1] = record; | ||
+ | |||
+ | abi_CMD_SAVE_STATE (saveData); | ||
+ | } | ||
+ | ON_CHECK_ROTATE () { | ||
+ | if (isLevelFinished) { | ||
+ | SaveGameState(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ===Time functions=== | ||
+ | ====abi_GetTime==== | ||
+ | Syntax: | ||
+ | abi_GetTime() | ||
+ | Description: | ||
+ | : Get current time in milliseconds. | ||
+ | |||
+ | ====Examples==== | ||
+ | new previousTime = 0; | ||
+ | new currentTime = 0; | ||
+ | new deltaTime = 0; | ||
+ | ON_INIT() { | ||
+ | previousTime = abi_GetTime(); | ||
+ | } | ||
+ | ONTICK() { | ||
+ | currentTime = abi_GetTime(); | ||
+ | deltaTime = currentTime - previousTime; | ||
+ | previousTime = currentTime; | ||
+ | } | ||
+ | |||
+ | |||
+ | ===Topology functions=== | ||
+ | ====get cube/face==== | ||
+ | Syntax: | ||
+ | abi_topCubeN(const _cubeN, const _faceN) | ||
+ | abi_topFaceN(const _cubeN, const _faceN) | ||
+ | abi_rightCubeN(const _cubeN, const _faceN) | ||
+ | abi_rightFaceN(const _cubeN, const _faceN) | ||
+ | abi_bottomCubeN(const _cubeN, const _faceN) | ||
+ | abi_bottomFaceN(const _cubeN, const _faceN) | ||
+ | abi_leftCubeN(const _cubeN, const _faceN) | ||
+ | abi_leftFaceN(const _cubeN, const _faceN) | ||
+ | Description: | ||
+ | : Returns the cube / screen located at the top / bottom / left / right of the specified in parameters. | ||
+ | |||
+ | ====Examples==== | ||
+ | Find diagonal face and cube | ||
+ | new diagonalCube = CUBES_MAX; | ||
+ | new diagonalFace = FACES_MAX; | ||
+ | new topCube = abi_topCubeN(cube, face); | ||
+ | new topFace = abi_topFaceN(cube, face); | ||
+ | if (topCube < CUBES_MAX) { | ||
+ | diagonalCube = abi_topCubeN(topCube, topFace); | ||
+ | if (diagonalCube < CUBES_MAX) { | ||
+ | diagonalFace = abi_topFaceN(topCube, topFace); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | ===Sound functions=== | ||
+ | ====abi_CMD_PLAYSND==== | ||
+ | Syntax: | ||
+ | abi_CMD_PLAYSND(const id, const volume) | ||
+ | Description: | ||
+ | : Play chosen sound with a given volume. | ||
+ | Arguments | ||
+ | : ''id'' | ||
+ | :: Sound serial number in the application package. | ||
+ | : ''volume'' | ||
+ | :: The sound volume. | ||
+ | |||
+ | |||
+ | ===Messages=== | ||
+ | ====abi_CMD_NET_TX==== | ||
+ | Syntax: | ||
+ | abi_CMD_NET_TX(const line_tx, const TTL, const data[]) | ||
+ | Description: | ||
+ | : Send data through given UART line with given TTL. | ||
+ | Arguments | ||
+ | : ''line_tx'' | ||
+ | :: UART line for sending a message. Each module has 3 UART lines. | ||
+ | : ''TTL'' | ||
+ | :: Message time to live. How many modules message will pass through before stopping. For example, set TTL to 0 message will transfer only to the neighbor module. Set TTL to 1 message will transfer to a neighbor of neighbor. Maximum TTL is 2. | ||
+ | : ''data'' | ||
+ | :: Data array to send. Maximum can be sent 20 bytes. The first 4 bytes are message general information that automatically adds before sending. The maximum useful data that can be sent are 16 bytes. Taking into account net command name 15 bytes. | ||
+ | |||
+ | ====Examples==== | ||
+ | We want to receive data only from 0 module | ||
+ | |||
+ | // define net command | ||
+ | #define NEW_TEST_NET_COMMAND P2P_CMD_BASE_SCRIPT_1 + 1 | ||
+ | |||
+ | // create message to send | ||
+ | Send_Test_Message() { | ||
+ | new data[4]; | ||
+ | data[0] = NEW_TEST_NET_COMMAND | (abi_cubeN << 8); | ||
+ | data[1] = add_game_data; | ||
+ | // using bitwise operations send more data | ||
+ | data[2] = add_script_data_1 | (add_script_data_2 << 8) | (add_script_data_3 << 16) | (add_script_data_4 << 24); | ||
+ | data[3] = add_game_data_1 | (add_game_data_2 << 16); | ||
+ | |||
+ | // send message through UART | ||
+ | abi_CMD_NET_TX(0, NET_BROADCAST_TTL_MAX, data); | ||
+ | abi_CMD_NET_TX(1, NET_BROADCAST_TTL_MAX, data); | ||
+ | abi_CMD_NET_TX(2, NET_BROADCAST_TTL_MAX, data); | ||
+ | } | ||
+ | |||
+ | // process the received message | ||
+ | ON_CMD_NET_RX (const pkt[]) { | ||
+ | // get 4 byte from incoming packet to get net command because first 4 bytes are general info | ||
+ | switch (abi_ByteN(pkt, 4)) { | ||
+ | case NEW_TEST_NET_COMMAND: { | ||
+ | if (abi_ByteN(pkt, 5) == 0) { | ||
+ | game_data = pkt[2]; | ||
+ | script_data_1 = abi_ByteN(pkt, 12); | ||
+ | script_data_2 = abi_ByteN(pkt, 13); | ||
+ | script_data_3 = abi_ByteN(pkt, 14); | ||
+ | script_data_4 = abi_ByteN(pkt, 15); | ||
+ | game_data_1 = pkt[4] & 0xFFFF; | ||
+ | game_data_2 = (pkt[4] >> 16) & 0xFFFF; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ===Physics functions=== | ||
+ | ====PHYSICS_CIRCLE_DATA==== | ||
+ | Syntax: | ||
+ | #define PHYSICS_CIRCLE_DATA .posX, .posY, .simplePosX, .simplePosY, .spdX, .spdY, .mass, .radius, .CoR, .cube, .face, .cubeT, .faceT | ||
+ | Description: | ||
+ | : PAWN symbolic subscript which represent stucture. | ||
+ | Fields | ||
+ | : ''posX'' | ||
+ | :: Circle position on X axis (fixed point) | ||
+ | : ''posY'' | ||
+ | :: Circle position on Y axis (fixed point) | ||
+ | : ''simplePosX'' | ||
+ | :: Circle position on X axis | ||
+ | : ''simplePosY'' | ||
+ | :: Circle position on Y axis | ||
+ | : ''spdX'' | ||
+ | :: Circle X speed | ||
+ | : ''spdY'' | ||
+ | :: Circle Y speed | ||
+ | : ''mass'' | ||
+ | :: Circle mass (fixed point) | ||
+ | : ''radius'' | ||
+ | :: Circle radius | ||
+ | : ''CoR'' | ||
+ | :: Coefficient of restitution (fixed point) | ||
+ | : ''cube'' | ||
+ | :: Module owner of this circle | ||
+ | : ''face'' | ||
+ | :: Face owner of this circle | ||
+ | : ''cubeT'' | ||
+ | :: Cube transfer, last module owner. Can be used for resending messages | ||
+ | : ''faceT'' | ||
+ | :: Face transfer, last face owner. Can be used for resending messages | ||
+ | |||
+ | ====Physics_Circle_Vs_Circle_obj==== | ||
+ | Syntax: | ||
+ | Physics_Circle_Vs_Circle_obj(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA]) | ||
+ | Description: | ||
+ | : Check circle versus circle collision. | ||
+ | Arguments: | ||
+ | : circle1 | ||
+ | :: First circle object. | ||
+ | : circle2 | ||
+ | :: Second circle object. | ||
+ | |||
+ | ====Physics_Circle_vs_AABB_obj==== | ||
+ | Syntax: | ||
+ | Physics_Circle_vs_AABB_obj(circle[PHYSICS_CIRCLE_DATA], rectX, rectY, rectWidth, rectHeight, fakeCircle[PHYSICS_CIRCLE_DATA] = 0) | ||
+ | Description: | ||
+ | : Check circle versus rectangle collision. | ||
+ | Arguments: | ||
+ | : circle | ||
+ | :: Circle object. | ||
+ | : rectX | ||
+ | :: X coordinate of top left rectangle corner. | ||
+ | : rectY | ||
+ | :: Y coordinate of top left rectangle corner. | ||
+ | : rectWidth | ||
+ | :: Rectangle width. | ||
+ | : rectHeight | ||
+ | :: Rectangle height. | ||
+ | : fakeCircle | ||
+ | :: In case of collision returns the collision point. | ||
+ | |||
+ | ====Physics_Circle_Vs_LineSegment==== | ||
+ | Syntax: | ||
+ | Physics_Circle_Vs_LineSegment(circle[PHYSICS_CIRCLE_DATA], lineSX, lineSY, lineEX, lineEY, fakeCircle[PHYSICS_CIRCLE_DATA] = 0) | ||
+ | Description: | ||
+ | : Check circle versus line segment collision. | ||
+ | Arguments: | ||
+ | : circle | ||
+ | :: Circle object. | ||
+ | : lineSX | ||
+ | :: Line start X coordinates. | ||
+ | : lineSY | ||
+ | :: Line start Y coordinate. | ||
+ | : lineEX | ||
+ | :: Line end X coordinate. | ||
+ | : lineEY | ||
+ | :: Line end Y coordinate. | ||
+ | : fakeCircle | ||
+ | :: In case of collision returns the collision point. | ||
+ | |||
+ | ====Physics_Res_CvC_Coll_Massless==== | ||
+ | Syntax: | ||
+ | Physics_Res_CvC_Coll_Massless(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA]) | ||
+ | Description: | ||
+ | : Collision resolves without using object mass. | ||
+ | Arguments: | ||
+ | : circle1 | ||
+ | :: First circle object. | ||
+ | : circle2 | ||
+ | :: Second circle object. | ||
+ | |||
+ | ====Physics_Res_CvC_Coll_Mass==== | ||
+ | Syntax: | ||
+ | Physics_Res_CvC_Coll_Mass(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA]) | ||
+ | Description: | ||
+ | : Resolves collision using object mass. | ||
+ | Arguments: | ||
+ | : circle1 | ||
+ | :: First circle object. | ||
+ | : circle2 | ||
+ | :: Second circle object. | ||
+ | |||
+ | ====Physics_DeserializeCircle==== | ||
+ | Syntax: | ||
+ | Physics_DeserializeCircle(serializedData_1, serializedData_2, circle[PHYSICS_CIRCLE_DATA]) | ||
+ | Description: | ||
+ | : Deserialize circle object. | ||
+ | Arguments: | ||
+ | : serializedData_1 | ||
+ | :: First part of serialized circle data. | ||
+ | : serializedData_2 | ||
+ | :: Second part of serialized circle data. | ||
+ | : circle | ||
+ | :: Circle object where need to save deserialized data. | ||
+ | |||
+ | ====Physics_SerializeCircle==== | ||
+ | Syntax: | ||
+ | Physics_SerializeCircle(obj[PHYSICS_CIRCLE_DATA], &serializedData_1, &serializedData_2) | ||
+ | Description: | ||
+ | : Serialize circle object. | ||
+ | Arguments: | ||
+ | : circle | ||
+ | :: Circle object to serialize. | ||
+ | : serializedData_1 | ||
+ | :: Return first part of serialized circle data. | ||
+ | : serializedData_2 | ||
+ | :: Return second part of serialized circle data. | ||
+ | |||
+ | ====Physics_Overlap==== | ||
+ | Syntax: | ||
+ | Physics_Overlap(overlap, positionDifference, distance) | ||
+ | Description: | ||
+ | : Returns the distance by which objects overlap. | ||
+ | Arguments: | ||
+ | : overlap | ||
+ | :: Half distance between two points. | ||
+ | : positionDifference | ||
+ | :: Position difference between two point in one axis. Example - first point position X is 10, second is 6. Then position difference is 10-6=4. | ||
+ | : distance | ||
+ | :: Distance between two points. | ||
+ | |||
+ | ====Examples==== | ||
+ | 1. Create circle object. | ||
+ | |||
+ | new ball_1[PHYSICS_CIRCLE_DATA]; | ||
+ | ball_1.posX = 180 << 8; | ||
+ | ball_1.posY = 180 << 8; | ||
+ | ball_1.simplePosX = 200; | ||
+ | ball_1.simplePosY = 180; | ||
+ | ball_1.spdX = -155; | ||
+ | ball_1.spdY = -155; | ||
+ | ball_1.mass = 5 << 8; | ||
+ | ball_1.radius = 16; | ||
+ | ball_1.cube = 0; | ||
+ | ball_1.face = 0; | ||
+ | ball_1.CoR = 150; | ||
+ | |||
+ | 2. Check collision of two circles and resolve it. | ||
+ | |||
+ | if (Physics_Circle_Vs_Circle_obj(ball_1, ball_2)) { | ||
+ | // Resolve collision | ||
+ | Physics_Res_CvC_Coll_Massless(ball_1, ball_2); | ||
+ | } | ||
+ | |||
+ | 3. Check collision of circle versus rectangle and resolve it. | ||
+ | |||
+ | new fakeCircle[PHYSICS_CIRCLE_DATA]; | ||
+ | if (Physics_Circle_vs_AABB_obj(ball, rectanglePosX, rectanglePosY, rectangleWidth, rectangleHeight, fakeCircle)) { | ||
+ | // Resolve collision | ||
+ | Physics_Res_CvC_Coll_Mass(ball, fakeCircle); | ||
+ | } | ||
+ | |||
+ | 4. Sending and receiving circle object. | ||
+ | |||
+ | // Sending message with ball object | ||
+ | SendBall (const pktNumber) { | ||
+ | new data[4]; | ||
+ | new serializedData_1, serializedData_2; | ||
+ | // Serialize 'ball' data | ||
+ | Physics_SerializeCircle(ball, serializedData_1, serializedData_2); | ||
+ | // Prepare message | ||
+ | data[0] = P2P_CMD_SEND_BALL; | ||
+ | data[1] = serializedData_1; | ||
+ | data[2] = serializedData_2; | ||
+ | data[3] = pktNumber; | ||
+ | // Broadcast message | ||
+ | abi_CMD_NET_TX(0, NET_BROADCAST_TTL_MAX, data); | ||
+ | abi_CMD_NET_TX(1, NET_BROADCAST_TTL_MAX, data); | ||
+ | abi_CMD_NET_TX(2, NET_BROADCAST_TTL_MAX, data); | ||
+ | } | ||
+ | |||
+ | // Receiving message with ball object | ||
+ | case P2P_CMD_SEND_BALL: { | ||
+ | new packetNumberReceived = pkt[4]; | ||
+ | if ((ballPacketNumber < packetNumberReceived) || ((ballPacketNumber - packetNumberReceived) > (0x7FFFFFFF >> 1))) { | ||
+ | ballPacketNumber = packetNumberReceived; | ||
+ | Physics_DeserializeCircle(pkt[2], pkt[3], ball); | ||
+ | } | ||
+ | } |
Latest revision as of 06:50, 11 February 2022
Contents
- 1 Introduction
- 1.1 WOWCube Paradigms
- 1.2 Pawn API
- 1.2.1 Graphic functions
- 1.2.2 Motion sensors
- 1.2.3 Save/load functions
- 1.2.4 Time functions
- 1.2.5 Topology functions
- 1.2.6 Sound functions
- 1.2.7 Messages
- 1.2.8 Physics functions
- 1.2.8.1 PHYSICS_CIRCLE_DATA
- 1.2.8.2 Physics_Circle_Vs_Circle_obj
- 1.2.8.3 Physics_Circle_vs_AABB_obj
- 1.2.8.4 Physics_Circle_Vs_LineSegment
- 1.2.8.5 Physics_Res_CvC_Coll_Massless
- 1.2.8.6 Physics_Res_CvC_Coll_Mass
- 1.2.8.7 Physics_DeserializeCircle
- 1.2.8.8 Physics_SerializeCircle
- 1.2.8.9 Physics_Overlap
- 1.2.8.10 Examples
Introduction
The main functions of the API are listed here, the features of the work of the environment are described
WOWCube Paradigms
WOWCube executes 8 copies of the byte-code of the script at the same time, providing functions for the interaction of scripts with each other, drawing functions, functions for accessing resources, and other specific functions. Each copy of the script has access to 3 displays. Resource scripts are packed into a package.
Pawn API
Graphic functions
Graphics 2D acceleration (G2D)
WOWCube provides the 2D acceleration interfaces to enhance gaming experience . Basically G2D engine allows to blend up to the 4 image layers at once with a HW acceleration. However there is no limit of layers, they are blended in a cascade. For example, if Pawn script requested 7 layers to be blended then 2 HW blending will occur:
Result of the blending can be saved as an internal G2D resource or flushed immediately on the specified display. Internal G2D resources can be used as an usual bitmap primitive (abi_CMD_BITMAP) or reused as an input for the next G2D action. Basic coordinate principle:
Coordinates are limited from -2048 to 2047. Maximum layers size is 240x240.
abi_CMD_G2D_BEGIN_BITMAP
Syntax:
abi_CMD_G2D_BEGIN_BITMAP(const resID, const width, const height, const bool:replace)
Description:
- abi_CMD_G2D_BEGIN_BITMAP and abi_CMD_G2D_END delimits the group of layers to be blended into internal G2D resource. This API is not intended for frequent usage. It is better suited for complex background generation on game initialization or dynamic resource modification triggered by rare game events.
Arguments:
- resID
- ID of the resource that will be generated from blending layers presented between abi_CMD_G2D_BEGIN_BITMAP and the subsequent abi_CMD_G2D_END. G2D engine can keep up to 3 different resources with IDs: 0, 1 and 2.
- width
- Width of the resulting resource. G2D engine can keep resource of 240px width maximum.
- height
- Height of the resulting resource. G2D engine can keep resource of 240px height maximum.
- replace
- If true, then an existing image will be replaced completely, otherwise it will be overwritten by reusing itself as a background layer.
abi_CMD_G2D_BEGIN_DISPLAY
Syntax:
abi_CMD_G2D_BEGIN_DISPLAY(const display, const bool:replace)
Description:
- abi_CMD_G2D_BEGIN_DISPLAY and abi_CMD_G2D_END delimits the group of layers to be blended directly into display framebuffer. Obviously this API is designed for rendering scene on game tick. This API is not limited by layers count as well as abi_CMD_G2D_BEGIN_BITMAP. However it is strictly recommended to blend no more than 4 layers. Otherwise cascade blending will be initiated resulting in some FPS drop.
Arguments:
- display
- ID of the display which framebuffer will be used for blending. Each module have 3 displays with ID starting from 0.
- replace
- If true then an existing image will be replaced completely, otherwise it will be overwritten by reusing itself as a background layer.
abi_CMD_G2D_ADD_SPRITE
Syntax:
abi_CMD_G2D_ADD_SPRITE(const resID, const bool:g2d, const x, const y, const alpha, const color, const rotation, const mirror)
Description:
- Specifies game resource which will be used as a layer for blending.
Arguments:
- resID
- ID of the resource to be uses as a layer.
- g2d
- Indicates if an internal G2D resource is specified or not.
- x, y
- Coordinates of the bitmap center to place on the layer.
- alpha
- Layer transparency in range between 0x00 and 0xFF, where 0x00 is a fully transparent layer.
- color
- Layer's source key - a color in ARGB8888 format to be avoided.
- rotation
- Clockwise rotation angle in degrees. It is possible to specify free angle, but only right angles have HW acceleration. Currently rotation only applicable for external resources.
- mirror
- Mirroring variant. Possible values are self-explained: MIRROR_BLANK, MIRROR_X, MIRROR_Y, MIRROR_XY.
abi_CMD_G2D_ADD_RECTANGLE
Syntax:
abi_CMD_G2D_ADD_RECTANGLE(const x, const y, const width, const height, const color)
Description:
- Specifies rectangle area which will be used as layer of blending. This API is not intended for frequent usage, i.e. particles generation. It is better suited for changing image background or applying color mask.
Arguments:
- x, y
- Coordinates of top left rectangle corner.
- width
- Rectangle width.
- height
- Rectangle height.
- color
- Rectangle color in ARGB8888 format.
abi_CMD_G2D_END
Syntax:
abi_CMD_G2D_END()
Description:
- abi_CMD_G2D_END() and abi_CMD_G2D_BEGIN_BITMAP/abi_CMD_G2D_BEGIN_DISPLAY delimits the group of layers to be blended. After abi_CMD_G2D_END call final blending will be initiated and results will be stored according to the begin comand.
Examples
1. Render into inner G2D resource buffer #face and display it on the display #face. Please, note that last argument of abi_CMD_BITMAP is a `true` flag, which means G2D resource should be used:
... abi_CMD_G2D_BEGIN_BITMAP(face, 240, 240, true); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize0, 120 - animationSquareSize0, animationSquareSize0 * 2, animationSquareSize0 * 2, 0xdfff0000); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize1, 120 - animationSquareSize1, animationSquareSize1 * 2, animationSquareSize1 * 2, 0xdfffff00); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize2, 120 - animationSquareSize2, animationSquareSize2 * 2, animationSquareSize2 * 2, 0xdfff00ff); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize3, 120 - animationSquareSize3, animationSquareSize3 * 2, animationSquareSize3 * 2, 0xdf00ffff); abi_CMD_G2D_ADD_SPRITE(resID, false, 120, 120, animationAlpha, 0x00000000, animationAngle, MIRROR_BLANK); abi_CMD_G2D_END(); ... abi_CMD_BITMAP(face, 120, 120, 0, MIRROR_BLANK, true); ... abi_CMD_REDRAW(face); ...
2. Render directly into display framebuffer #face. This will produce same result on display as example #1, but the generated image is not saved:
... abi_CMD_G2D_BEGIN_DISPLAY(face, true); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize0, 120 - animationSquareSize0, animationSquareSize0 * 2, animationSquareSize0 * 2, 0xdfff0000); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize1, 120 - animationSquareSize1, animationSquareSize1 * 2, animationSquareSize1 * 2, 0xdfffff00); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize2, 120 - animationSquareSize2, animationSquareSize2 * 2, animationSquareSize2 * 2, 0xdfff00ff); abi_CMD_G2D_ADD_RECTANGLE(120 - animationSquareSize3, 120 - animationSquareSize3, animationSquareSize3 * 2, animationSquareSize3 * 2, 0xdf00ffff); abi_CMD_G2D_ADD_SPRITE(resID, false, 120, 120, animationAlpha, 0x00000000, animationAngle, MIRROR_BLANK); abi_CMD_G2D_END(); ...
Font drawing functions
abi_CMD_TEXT
API:
abi_CMD_TEXT(const text[], const fontResID, const x, const y, const scale, const angle, const r, const g, const b)
Description:
- Intended to render a system font or a custom font from resources with specified coordinates, scale and rotation at an arbitrary angle.
Arguments:
- text
- Array of chars.
- fontResID
- Custom font resource identifier. Provide -1 to use system font resource.
- x, y
- Coordinates of top left rectangle corner.
- scale, angle
- Percentage scale and clockwise rotation angle in degrees. Max size of font is 200x200 px. (scale = 100%)
- r, g, b
- Font color in RGB format.
Example:
new text[4] = ['A', 'p', 'p', '\0']; abi_CMD_TEXT(text, RES_ID_FONT, 90, 160, 16, current_angles[face], 255, 0, 0);
TEXTURE drawing functions
abi_CMD_DYNAMIC_TEXTURE
API:
abi_CMD_DYNAMIC_TEXTURE(const effectId = 1, const time = any value, const args[] = {0x04030201, 0x08070605, 0x00000A09}, const argsCount = 3, const bool:g2d = false)
Description:
- Render a texture with chosen algorithm and parameters.
Arguments:
- effectId
- Define algorithm to render texture.
- Available values : G2D_DYNAMIC_TEXTURE_MOSAIC
- time
- Current time value. Use any fixed value to static texture or set current time value in milliseconds to make texture alive.
- args, argsCount
- Byte stream of algorithm settings it's aligned to 4 bytes, because of pawn supports only 32-bit values.
- Size of array depends on algorithm. For example mosaic algorithm has size of settings equals 10 bytes , so we must use aligned 4 bytes - 12 bytes array and argsCount = 3
- g2d
- false - Use pawn default buffer to draw texture.
- true - Use g2d buffer to draw texture - not supported now.
G2D_DYNAMIC_TEXTURE_MOSAIC alogrithm description
- So in effect named 'mosaic' we have settings of 10 parameters each one 1 byte
- Noise factors :
- factor x : values from 0 to 10
- factor y : values from 0 to 10
- factor xy : values from 0 to 10
- Time factors :
- factor x : values from 0 to 10
- factor y : values from 0 to 10
- factor xy : values from 0 to 10
- Color factors :
- r : values from 0 to 10
- g : values from 0 to 10
- b : values from 0 to 10
- Zoom factor :
- zoom values from 0 to 10
For example we want to set all parameters above with values in order 1,2,3,4,5,6,7,8,9,10. Take in attention that each parameter is 1 byte we must make array of 32-bit values 0x04030201, 0x08070605, 0x00000A09
Example:
mosaic_effect_settings = { 0x04030201, 0x08070605, 0x00000A09 }; mosaic_effect_settings_length = 3; abi_CMD_DYNAMIC_TEXTURE(G2D_DYNAMIC_TEXTURE_MOSAIC , currentTime, mosaic_effect_settings, mosaic_effect_settings_length);
Motion sensors
abi_MTD_GetFaceAccel(X/Y/Z)
Syntax:
abi_MTD_GetFaceAccelX(const faceN) abi_MTD_GetFaceAccelY(const faceN) abi_MTD_GetFaceAccelZ(const faceN)
Description:
- Get the value of acceleration along the requested axis.
Arguments
- faceN
- Number of the module face for which requested axis is belong.
abi_MTD_GetFaceGyro(X/Y/Z)
Syntax:
abi_MTD_GetFaceGyroX(const faceN) abi_MTD_GetFaceGyroY(const faceN) abi_MTD_GetFaceGyroZ(const faceN)
Description:
- Get the gyro value around the requested axis.
Arguments
- faceN
- Number of the module face for which requested axis is belong.
abi_MTD_GetTapFace
Syntax:
abi_MTD_GetTapFace()
Description:
- Get the face ID which was tapped. ID is not a face number which is used for drawing in abi_CMD_G2D_BEGIN_DISPLAY or abi_CMD_REDRAW, but that number can be calculated by subtracting by one from ID value. See possible values below.
Return values:
- MTD_TAP_DIRECTION_NONE = 0
- Indicates that the module wan not tapped.
- MTD_TAP_DIRECTION_X = 1
- MTD_TAP_DIRECTION_Y = 2
- MTD_TAP_DIRECTION_Z = 3
- Indicated direction of tap.
abi_MTD_IsTapOpposite
Syntax:
abi_MTD_IsTapOpposite()
Description:
- Get the flag if the tap was detected in opposite direction.
abi_MTD_GetTapsCount
Syntax:
abi_MTD_GetTapsCount()
Description:
- Get the count of subsequent taps. Tap is treated as a subsequent if it was detected within predefined interval (350ms). Count will be zero until sequence is finished, i.e. next tap is not detected within interval.
abi_checkShake
Syntax:
abi_checkShake()
Description:
- Checks if the number of shakes of the cube was more than a certain threshold then exits the script
Examples
1. Flash the face on which tap was detected. Print an ID of that face. Color of the flash depends on taps count: red - one tap, green - two taps and blue - three.
new delay = 0; new color = 0x000000; ONTICK() { if (!color) { switch (abi_MTD_GetTapsCount()) { case 1: color = 0xff0000; case 2: color = 0x00ff00; case 3: color = 0x0000ff; } } if (delay % 25 == 0) { for (new i = 0; i < FACES_MAX; i++) { if (i == (abi_MTD_GetTapFace() - 1)) { abi_CMD_FILL_2(color); color = 0x000000; switch (abi_MTD_GetTapFace()) { case 1: abi_CMD_TEXT(['1', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); case 2: abi_CMD_TEXT(['2', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); case 3: abi_CMD_TEXT(['3', '\0'], -1, 120, 120, 14, 0, 0xff, 0xff, 0xff); } } else { abi_CMD_FILL(0, 0, 0); } abi_CMD_REDRAW(i); } } delay++; }
2. Exit from script
ONTICK() { if (abi_cubeN == 0) { abi_checkShake(); } // Script logic }
Save/load functions
abi_CMD_SAVE_STATE
Syntax:
bool:abi_CMD_SAVE_STATE(const data[], size = sizeof(data))
Description:
- Save maximum 256 bytes of data to wowcube flash memory.
Arguments
- data
- Game data to save.
- size
- Size of game data.
Return values:
- return false
- If size is bigger then 256 bytes.
abi_CMD_LOAD_STATE
Syntax:
abi_CMD_LOAD_STATE()
Description:
- Sends a command requesting the platform to load script data. The response from the platform is not instantaneous and takes several milliseconds.
Examples
1. Load data at the start.
// This function is called when a response is received from the platform ON_LOAD_GAME_DATA (const pkt[]) { // Deserialize pkt currentLevelNumber = pkt[1]; // Starting with 1 cause 0 pkt element holding command ID score = pkt[2]; moves = pkt[3]; ... record = pkt[GAME_SAVE_SIZE]; } ON_INIT () { abi_CMD_LOAD_STATE (); }
2. Save the data after the end of the level.
SaveGameState () { new saveData [GAME_SAVE_SIZE]; // Assign all necessary data saveData[0] = currentLevelNumber; saveData[1] = score; saveData[2] = moves; ... saveData[GAME_SAVE_SIZE - 1] = record; abi_CMD_SAVE_STATE (saveData); } ON_CHECK_ROTATE () { if (isLevelFinished) { SaveGameState(); } }
Time functions
abi_GetTime
Syntax:
abi_GetTime()
Description:
- Get current time in milliseconds.
Examples
new previousTime = 0; new currentTime = 0; new deltaTime = 0; ON_INIT() { previousTime = abi_GetTime(); } ONTICK() { currentTime = abi_GetTime(); deltaTime = currentTime - previousTime; previousTime = currentTime; }
Topology functions
get cube/face
Syntax:
abi_topCubeN(const _cubeN, const _faceN) abi_topFaceN(const _cubeN, const _faceN) abi_rightCubeN(const _cubeN, const _faceN) abi_rightFaceN(const _cubeN, const _faceN) abi_bottomCubeN(const _cubeN, const _faceN) abi_bottomFaceN(const _cubeN, const _faceN) abi_leftCubeN(const _cubeN, const _faceN) abi_leftFaceN(const _cubeN, const _faceN)
Description:
- Returns the cube / screen located at the top / bottom / left / right of the specified in parameters.
Examples
Find diagonal face and cube
new diagonalCube = CUBES_MAX; new diagonalFace = FACES_MAX; new topCube = abi_topCubeN(cube, face); new topFace = abi_topFaceN(cube, face); if (topCube < CUBES_MAX) { diagonalCube = abi_topCubeN(topCube, topFace); if (diagonalCube < CUBES_MAX) { diagonalFace = abi_topFaceN(topCube, topFace); } }
Sound functions
abi_CMD_PLAYSND
Syntax:
abi_CMD_PLAYSND(const id, const volume)
Description:
- Play chosen sound with a given volume.
Arguments
- id
- Sound serial number in the application package.
- volume
- The sound volume.
Messages
abi_CMD_NET_TX
Syntax:
abi_CMD_NET_TX(const line_tx, const TTL, const data[])
Description:
- Send data through given UART line with given TTL.
Arguments
- line_tx
- UART line for sending a message. Each module has 3 UART lines.
- TTL
- Message time to live. How many modules message will pass through before stopping. For example, set TTL to 0 message will transfer only to the neighbor module. Set TTL to 1 message will transfer to a neighbor of neighbor. Maximum TTL is 2.
- data
- Data array to send. Maximum can be sent 20 bytes. The first 4 bytes are message general information that automatically adds before sending. The maximum useful data that can be sent are 16 bytes. Taking into account net command name 15 bytes.
Examples
We want to receive data only from 0 module
// define net command #define NEW_TEST_NET_COMMAND P2P_CMD_BASE_SCRIPT_1 + 1 // create message to send Send_Test_Message() { new data[4]; data[0] = NEW_TEST_NET_COMMAND | (abi_cubeN << 8); data[1] = add_game_data; // using bitwise operations send more data data[2] = add_script_data_1 | (add_script_data_2 << 8) | (add_script_data_3 << 16) | (add_script_data_4 << 24); data[3] = add_game_data_1 | (add_game_data_2 << 16); // send message through UART abi_CMD_NET_TX(0, NET_BROADCAST_TTL_MAX, data); abi_CMD_NET_TX(1, NET_BROADCAST_TTL_MAX, data); abi_CMD_NET_TX(2, NET_BROADCAST_TTL_MAX, data); } // process the received message ON_CMD_NET_RX (const pkt[]) { // get 4 byte from incoming packet to get net command because first 4 bytes are general info switch (abi_ByteN(pkt, 4)) { case NEW_TEST_NET_COMMAND: { if (abi_ByteN(pkt, 5) == 0) { game_data = pkt[2]; script_data_1 = abi_ByteN(pkt, 12); script_data_2 = abi_ByteN(pkt, 13); script_data_3 = abi_ByteN(pkt, 14); script_data_4 = abi_ByteN(pkt, 15); game_data_1 = pkt[4] & 0xFFFF; game_data_2 = (pkt[4] >> 16) & 0xFFFF; } } } }
Physics functions
PHYSICS_CIRCLE_DATA
Syntax:
#define PHYSICS_CIRCLE_DATA .posX, .posY, .simplePosX, .simplePosY, .spdX, .spdY, .mass, .radius, .CoR, .cube, .face, .cubeT, .faceT
Description:
- PAWN symbolic subscript which represent stucture.
Fields
- posX
- Circle position on X axis (fixed point)
- posY
- Circle position on Y axis (fixed point)
- simplePosX
- Circle position on X axis
- simplePosY
- Circle position on Y axis
- spdX
- Circle X speed
- spdY
- Circle Y speed
- mass
- Circle mass (fixed point)
- radius
- Circle radius
- CoR
- Coefficient of restitution (fixed point)
- cube
- Module owner of this circle
- face
- Face owner of this circle
- cubeT
- Cube transfer, last module owner. Can be used for resending messages
- faceT
- Face transfer, last face owner. Can be used for resending messages
Physics_Circle_Vs_Circle_obj
Syntax:
Physics_Circle_Vs_Circle_obj(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
Description:
- Check circle versus circle collision.
Arguments:
- circle1
- First circle object.
- circle2
- Second circle object.
Physics_Circle_vs_AABB_obj
Syntax:
Physics_Circle_vs_AABB_obj(circle[PHYSICS_CIRCLE_DATA], rectX, rectY, rectWidth, rectHeight, fakeCircle[PHYSICS_CIRCLE_DATA] = 0)
Description:
- Check circle versus rectangle collision.
Arguments:
- circle
- Circle object.
- rectX
- X coordinate of top left rectangle corner.
- rectY
- Y coordinate of top left rectangle corner.
- rectWidth
- Rectangle width.
- rectHeight
- Rectangle height.
- fakeCircle
- In case of collision returns the collision point.
Physics_Circle_Vs_LineSegment
Syntax:
Physics_Circle_Vs_LineSegment(circle[PHYSICS_CIRCLE_DATA], lineSX, lineSY, lineEX, lineEY, fakeCircle[PHYSICS_CIRCLE_DATA] = 0)
Description:
- Check circle versus line segment collision.
Arguments:
- circle
- Circle object.
- lineSX
- Line start X coordinates.
- lineSY
- Line start Y coordinate.
- lineEX
- Line end X coordinate.
- lineEY
- Line end Y coordinate.
- fakeCircle
- In case of collision returns the collision point.
Physics_Res_CvC_Coll_Massless
Syntax:
Physics_Res_CvC_Coll_Massless(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
Description:
- Collision resolves without using object mass.
Arguments:
- circle1
- First circle object.
- circle2
- Second circle object.
Physics_Res_CvC_Coll_Mass
Syntax:
Physics_Res_CvC_Coll_Mass(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
Description:
- Resolves collision using object mass.
Arguments:
- circle1
- First circle object.
- circle2
- Second circle object.
Physics_DeserializeCircle
Syntax:
Physics_DeserializeCircle(serializedData_1, serializedData_2, circle[PHYSICS_CIRCLE_DATA])
Description:
- Deserialize circle object.
Arguments:
- serializedData_1
- First part of serialized circle data.
- serializedData_2
- Second part of serialized circle data.
- circle
- Circle object where need to save deserialized data.
Physics_SerializeCircle
Syntax:
Physics_SerializeCircle(obj[PHYSICS_CIRCLE_DATA], &serializedData_1, &serializedData_2)
Description:
- Serialize circle object.
Arguments:
- circle
- Circle object to serialize.
- serializedData_1
- Return first part of serialized circle data.
- serializedData_2
- Return second part of serialized circle data.
Physics_Overlap
Syntax:
Physics_Overlap(overlap, positionDifference, distance)
Description:
- Returns the distance by which objects overlap.
Arguments:
- overlap
- Half distance between two points.
- positionDifference
- Position difference between two point in one axis. Example - first point position X is 10, second is 6. Then position difference is 10-6=4.
- distance
- Distance between two points.
Examples
1. Create circle object.
new ball_1[PHYSICS_CIRCLE_DATA]; ball_1.posX = 180 << 8; ball_1.posY = 180 << 8; ball_1.simplePosX = 200; ball_1.simplePosY = 180; ball_1.spdX = -155; ball_1.spdY = -155; ball_1.mass = 5 << 8; ball_1.radius = 16; ball_1.cube = 0; ball_1.face = 0; ball_1.CoR = 150;
2. Check collision of two circles and resolve it.
if (Physics_Circle_Vs_Circle_obj(ball_1, ball_2)) { // Resolve collision Physics_Res_CvC_Coll_Massless(ball_1, ball_2); }
3. Check collision of circle versus rectangle and resolve it.
new fakeCircle[PHYSICS_CIRCLE_DATA]; if (Physics_Circle_vs_AABB_obj(ball, rectanglePosX, rectanglePosY, rectangleWidth, rectangleHeight, fakeCircle)) { // Resolve collision Physics_Res_CvC_Coll_Mass(ball, fakeCircle); }
4. Sending and receiving circle object.
// Sending message with ball object SendBall (const pktNumber) { new data[4]; new serializedData_1, serializedData_2; // Serialize 'ball' data Physics_SerializeCircle(ball, serializedData_1, serializedData_2); // Prepare message data[0] = P2P_CMD_SEND_BALL; data[1] = serializedData_1; data[2] = serializedData_2; data[3] = pktNumber; // Broadcast message abi_CMD_NET_TX(0, NET_BROADCAST_TTL_MAX, data); abi_CMD_NET_TX(1, NET_BROADCAST_TTL_MAX, data); abi_CMD_NET_TX(2, NET_BROADCAST_TTL_MAX, data); }
// Receiving message with ball object case P2P_CMD_SEND_BALL: { new packetNumberReceived = pkt[4]; if ((ballPacketNumber < packetNumberReceived) || ((ballPacketNumber - packetNumberReceived) > (0x7FFFFFFF >> 1))) { ballPacketNumber = packetNumberReceived; Physics_DeserializeCircle(pkt[2], pkt[3], ball); } }