diff --git a/allegro.js b/allegro.js index e0dadf7..e66feaf 100644 --- a/allegro.js +++ b/allegro.js @@ -1867,7 +1867,9 @@ function log(string) { if (ALLEGRO_CONSOLE && console) console.log(string); if (!_debug_enabled) return; - _debug_element.innerHTML = _debug_element.innerHTML + string + "
"; + if (_debug_element.nodeName.toLowerCase() == "textarea") _debug_element.value = _debug_element.value + string + "\n"; + else _debug_element.innerHTML = _debug_element.innerHTML + string + "
"; + _debug_element.scrollTop = _debug_element.scrollHeight; } /// Wipes the debug console @@ -1875,7 +1877,8 @@ function log(string) function wipe_log() { if (!_debug_enabled) return; - _debug_element.innerHTML = ""; + if (_debug_element.nodeName.toLowerCase() == "textarea") _debug_element.value = ""; + else _debug_element.innerHTML = ""; } //@} diff --git a/emscripten/README.md b/emscripten/README.md new file mode 100644 index 0000000..dceb059 --- /dev/null +++ b/emscripten/README.md @@ -0,0 +1,35 @@ +## A lousy C port of a lousy JS port of a C library + +*Allegro have been to JS and back* + +**You think you're a hardcore allegro programmer? PROVE IT!** + +### How do I make a C game for allegro.js? + +1. Clone this repository +2. Install emscripten +3. Read `allegro.h` +4. Read and understand the examples +5. Write code +6. Compile-it +7. Enjoy + +You don't need to write a single line of Javascript or HTML ! ! + +### How different is it from allegro.js + +There is several tiny differences: +* All globals are functions (because emscripten) +* Because of name clash, rand and log have been renamed to rand16 and logmsg +* When passing an array parameter, you'll also have to pass its length +* There is no such thing as default parameters, closures, etc. (this is C programming, for real) + +### How to compile C code into an HTML+Javascript program? + +Compile your code with `emcc`: +```bash +emcc --pre-js ../allegro.js --js-library ../allegro.js --js-library library.js -I. -o my_game.html my_game.c +``` + +Open the created html file with your favorite JS enabled internet browser. + diff --git a/emscripten/allegro.h b/emscripten/allegro.h new file mode 100644 index 0000000..e09e8de --- /dev/null +++ b/emscripten/allegro.h @@ -0,0 +1,201 @@ +/** + I'm the C header, #include me! +**/ + +#ifndef _ALLEGRO_JS_H +#define _ALLEGRO_JS_H +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* CONFIGURATION ROUTINES */ +extern void install_allegro(void); +extern void allegro_init(void); +extern void allegro_init_all(const char *canvas_id, int w, int h, int menu, const int *enable_keys, int enable_keys_len); +#define END_OF_MAIN() + +/* MOUSE ROUTINES */ +extern int mouse_b(void); +extern int mouse_pressed(void); +extern int mouse_released(void); +extern int mouse_x(void); +extern int mouse_y(void); +extern int mouse_z(void); +extern int mouse_mx(void); +extern int mouse_my(void); +extern int mouse_mz(void); + +extern int install_mouse(int menu); +extern int remove_mouse(void); +extern int show_mouse(void); +extern int hide_mouse(void); + +/* TOUCH ROUTINES */ +typedef struct { + int x, y, mx, my, px, py, sx, sy, id, age, dead; +} TOUCH_OBJECT; +extern TOUCH_OBJECT* touch(int *len); +extern TOUCH_OBJECT* touch_pressed(int *len); +extern TOUCH_OBJECT* touch_released(int *len); +extern void install_touch(void); +extern void remove_touch(void); + +/* TIMER ROUTINES */ +#define SECS_TO_TIMER(secs) ( secs*1000 ) +#define MSEC_TO_TIMER(msec) ( msec ) +#define BPS_TO_TIMER(bps) ( 1000./(float)bps ) +#define BPM_TO_TIMER(bpm) ( 60*1000./(float)bpm ) +typedef void (*procedure)(void); +typedef void (*bar)(float progress); +extern void install_timer(void); +extern long altime(void); +extern void install_int(procedure p, long msec); +extern void install_int_ex(procedure p, long speed); +extern void loop(procedure p, long speed); +extern void loading_bar(float progress); +extern void ready(procedure p, bar b); +extern void remove_int(procedure p); +extern void remove_all_ints(void); + +/* KEYBOARD ROUTINES */ +const char KEY_A = 0x41, KEY_B = 0x42, KEY_C = 0x43, KEY_D = 0x44, KEY_E = 0x45, KEY_F = 0x46, KEY_G = 0x47, + KEY_H = 0x48, KEY_I = 0x49, KEY_J = 0x4A, KEY_K = 0x4B, KEY_L = 0x4C, KEY_M = 0x4D, KEY_N = 0x4E, + KEY_O = 0x4F, KEY_P = 0x50, KEY_Q = 0x51, KEY_R = 0x52, KEY_S = 0x53, KEY_T = 0x54, KEY_U = 0x55, + KEY_V = 0x56, KEY_W = 0x57, KEY_X = 0x58, KEY_Y = 0x59, KEY_Z = 0x5A, + KEY_0 = 0x30, KEY_1 = 0x31, KEY_2 = 0x32, KEY_3 = 0x33, KEY_4 = 0x34, KEY_5 = 0x35, KEY_6 = 0x36, + KEY_7 = 0x37, KEY_8 = 0x38, KEY_9 = 0x39, + KEY_0_PAD = 0x60, KEY_1_PAD = 0x61, KEY_2_PAD = 0x62, KEY_3_PAD = 0x63, KEY_4_PAD = 0x64, KEY_5_PAD = 0x65, + KEY_6_PAD = 0x66, KEY_7_PAD = 0x67, KEY_8_PAD = 0x68, KEY_9_PAD = 0x69, + KEY_F1 = 0x70, KEY_F2 = 0x71, KEY_F3 = 0x72, KEY_F4 = 0x73, KEY_F5 = 0x74, KEY_F6 = 0x75, KEY_F7 = 0x76, + KEY_F8 = 0x77, KEY_F9 = 0x78, KEY_F10 = 0x79, KEY_F11 = 0x7a, KEY_F12 = 0x7b, + KEY_ESC = 0x1B, KEY_TILDE = 0xc0, KEY_MINUS = 0xbd, KEY_EQUALS = 0xbb, KEY_BACKSPACE = 0x08, KEY_TAB = 0x09, + KEY_OPENBRACE = 0xdb, KEY_CLOSEBRACE = 0xdd, KEY_ENTER = 0x0D, KEY_COLON = 0xba, KEY_QUOTE = 0xde, + KEY_BACKSLASH = 0xdc, KEY_COMMA = 0xbc, KEY_STOP = 0xbe, KEY_SLASH = 0xBF, KEY_SPACE = 0x20, + KEY_INSERT = 0x2D, KEY_DEL = 0x2E, KEY_HOME = 0x24, KEY_END = 0x23, KEY_PGUP = 0x21, KEY_PGDN = 0x22, + KEY_LEFT = 0x25, KEY_RIGHT = 0x27, KEY_UP = 0x26, KEY_DOWN = 0x28, KEY_SLASH_PAD = 0x6F, KEY_ASTERISK = 0x6A, + KEY_MINUS_PAD = 0x6D, KEY_PLUS_PAD = 0x6B, KEY_ENTER_PAD = 0x0D, KEY_PRTSCR = 0x2C, KEY_PAUSE = 0x13, + KEY_EQUALS_PAD = 0x0C, KEY_LSHIFT = 0x10, KEY_RSHIFT = 0x10, KEY_LCONTROL = 0x11, KEY_RCONTROL = 0x11, + KEY_ALT = 0x12, KEY_ALTGR = 0x12, KEY_LWIN = 0x5b, KEY_RWIN = 0x5c, KEY_MENU = 0x5d, KEY_SCRLOCK = 0x9d, + KEY_NUMLOCK = 0x90, KEY_CAPSLOCK = 0x14; +extern int* key(void); +extern int* pressed(void); +extern int* released(void); +extern int install_keyboard(const int *enable_keys, int enable_keys_len); +extern int remove_keyboard(void); + +/* BITMAP ROUTINES */ +typedef struct { + int handle; + int w, h; +} BITMAP_OBJECT; +extern BITMAP_OBJECT* create_bitmap(int width, int height); +extern BITMAP_OBJECT* load_bitmap(const char *filename); +extern BITMAP_OBJECT* load_bmp(const char *filename); +extern BITMAP_OBJECT** load_sheet(const char *filename, int w, int h, int *len); + +/* GRAPHICS MODES */ +extern BITMAP_OBJECT* canvas(void); +extern int SCREEN_W(void); +extern int SCREEN_H(void); +extern int set_gfx_mode(const char *canvas_id, int width, int height, int smooth); + +/* DRAWING PRIMITIVES */ +#define PI = 3.14159265 +#define PI2 = 6.2831853 +#define PI_2 = 1.570796325 +#define PI_3 = 1.04719755 +#define PI_4 = 0.7853981625 +#define RAD(d) ( -d*PI/180.0 ) +#define DEG(r) ( -r*180.0/PI ) +extern int makecol(char r, char g, char b, char a); +extern int makecolf(float r, float g, float b, float a); +extern char getr(int colour); +extern char getg(int colour); +extern char getb(int colour); +extern char geta(int colour); +extern float getrf(int colour); +extern float getgf(int colour); +extern float getbf(int colour); +extern float getaf(int colour); +extern int getpixel(BITMAP_OBJECT *bitmap, int x, int y); +extern void putpixel(BITMAP_OBJECT *bitmap, int x, int y, int colour); +extern void clear_bitmap(BITMAP_OBJECT *bitmap); +extern void clear_to_color(BITMAP_OBJECT *bitmap, int colour); +extern void line(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int colour, int width); +extern void vline(BITMAP_OBJECT *bitmap, int x, int y1, int y2, int colour, int width); +extern void hline(BITMAP_OBJECT *bitmap, int x1, int y, int x2, int colour, int width); +extern void triangle(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int x3, int y3, int colour, int width); +extern void trianglefill(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int x3, int y3, int colour); +extern void polygon(BITMAP_OBJECT *bitmap, int vertices, const int *points, int colour, int width); +extern void polygonfill(BITMAP_OBJECT *bitmap, int vertices, const int *points, int colour); +extern void rect(BITMAP_OBJECT *bitmap, int x, int y, int w, int h, int colour, int width); +extern void rectfill(BITMAP_OBJECT *bitmap, int x, int y, int w, int h, int colour); +extern void circle(BITMAP_OBJECT *bitmap, int x, int y, int radius, int colour, int width); +extern void circlefill(BITMAP_OBJECT *bitmap, int x, int y, int radius, int colour); +extern void arc(BITMAP_OBJECT *bitmap, int x, int y, float ang1, float ang2, int radius, int colour, int width); +extern void arcfill(BITMAP_OBJECT *bitmap, int x, int y, float ang1, float ang2, int radius, int colour); + +/* BLITTING AND SPRITES */ +extern void draw_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y); +extern void scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float sx, float sy); +extern void rotate_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float angle); +extern void pivot_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, int cx, int cy, float angle); +extern void rotate_scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float angle, float sx, float sy); +extern void pivot_scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, int cx, int cy, float angle, float sx, float sy); +extern void blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int sx, int sy, int dx, int dy, int w, int h); +extern void simple_blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int x, int y); +extern void stretch_blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh); + +/* TEXT OUTPUT */ +typedef int FONT_OBJECT; +extern FONT_OBJECT* font(void); +extern FONT_OBJECT* load_base64_font(char *data); +extern FONT_OBJECT* load_font(char *filename); +extern FONT_OBJECT* create_font(char *family); +extern void textout(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width); +extern void textout_centre(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width); +extern void textout_right(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width); + +/* SOUND ROUTINES */ +typedef int SAMPLE_OBJECT; +extern void install_sound(void); +extern void set_volume(float volume); +extern float get_volume(void); +extern SAMPLE_OBJECT* load_sample(char *filename); +extern void destroy_sample(char *filename); +extern void play_sample(SAMPLE_OBJECT *sample, float vol, float freq, int loop); +extern void adjust_sample(SAMPLE_OBJECT *sample, float vol, float freq, int loop); +extern void stop_sample(SAMPLE_OBJECT *sample); +extern void pause_sample(SAMPLE_OBJECT *sample); + +/* HELPER MATH FUNCTIONS */ +extern unsigned short rand16(void); +extern int rand32(void); +extern float frand(void); +#define abs(a) ( (a<0)?(-a):(a) ) +extern float length(float x, float y); +extern float distance(float x1, float y1, float x2, float y2); +extern float distance2(float x1, float y1, float x2, float y2); +extern float linedist(float ex1, float ey1, float ex2, float ey2, float x, float y); +extern float lerp(float from, float to, float progress); +extern float dot(float x1, float y1, float x2, float y2); +extern int sgn(float a); +extern float angle(float x1, float y1, float x2, float y2); +extern float anglediff(float a, float b); +extern float clamp(float value, float min, float max); +extern float scale(float value, float min, float max, float min2, float max2); +extern float scaleclamp(float value, float min, float max, float min2, float max2); + +/* DEBUG FUNCTIONS */ +extern int ALLEGRO_CONSOLE; +extern void enable_debug(const char *id); +extern void logmsg(const char *string); +extern void wipe_log(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ALLEGRO_JS_H */ diff --git a/emscripten/examples/exbmp.c b/emscripten/examples/exbmp.c new file mode 100644 index 0000000..0078658 --- /dev/null +++ b/emscripten/examples/exbmp.c @@ -0,0 +1,26 @@ +#include +#include + +// Globally declared bitmap object +BITMAP_OBJECT *logo; + +void when_ready(void) { + // Renders the loaded image on the screen + stretch_blit(logo, canvas(), 0, 0, logo->w, logo->h, 0, 0, SCREEN_W(), SCREEN_H()); +} + +int main(void) { + // Initialises allegro.js + allegro_init(); + + // Installs graphics at given canvas in 640x480 resolution + set_gfx_mode("canvas", 640, 480, 1); + + // Loads an image into the bitmap object + logo = load_bmp("data/allegro.png"); + + ready(when_ready, NULL); + + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/exbounce.c b/emscripten/examples/exbounce.c new file mode 100644 index 0000000..d1927bd --- /dev/null +++ b/emscripten/examples/exbounce.c @@ -0,0 +1,94 @@ +#include +#include + +// bitmap objects +BITMAP_OBJECT *clouds, *ball; + +// sample object +SAMPLE_OBJECT *bounce; + +// size and speed of the ball +const int size=64, speed=5; + +// positon of the ball +float cx=100, cy=100; + +// velocity of the ball +float vx=speed, vy=speed; + +// drawing function +void draw(void) +{ + // draw allegro clouds background + stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H()); + + // draws the ball centered + draw_sprite(canvas(), ball, cx, cy); +} + +// update game logic +void update(void) { + // did the ball bounce off the wall this turn? + int bounced = 0; + + // if the ball is going to collide with screen bounds + // after applying velocity, if so, reverse velocity + // and remember that it bonced + if (cx+vx > SCREEN_W()) { vx = -speed; bounced=1; } + if (cy+vy > SCREEN_H()) { vy = -speed*3; bounced=1; } + if (cx+vx < 0) { vx = speed; bounced=1; } + if (cy+vy < 0) { vy = speed; bounced=1; } + + // move the ball + cx += vx; + cy += vy; + + // if it bounced, play a sound + if (bounced) play_sample(bounce, 1., 1., 0); + + // add gravity + vy += .3; +} + +void in_loop(void) { + // clear screen + clear_to_color(canvas(), makecol(255, 255, 255, 255)); + + // update game logic + update(); + + // render everything + draw(); +} + +void when_ready(void) { + loop(in_loop, BPS_TO_TIMER(60)); +} + +// entry point of our example +int main(void) { + // enable debugging to console element + enable_debug("output"); + + // put allegro in canvas with id="canvas" + // make the dimesnions 640x480 + set_gfx_mode("canvas", 640, 480, 1); + + install_sound(); + + // load ball image + ball = load_bmp("data/planet.png"); + + // load background image + clouds = load_bmp("data/clouds.png"); + + // load the bounce sound + bounce = load_sample("data/bounce.mp3"); + + // make sure everything has loaded + ready(when_ready, NULL); + + // the end + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/exgame.c b/emscripten/examples/exgame.c new file mode 100644 index 0000000..6a7149a --- /dev/null +++ b/emscripten/examples/exgame.c @@ -0,0 +1,85 @@ +#include +#include +#include + +//bitmap objects +BITMAP_OBJECT *man, *apple, *bg; + +// munching soudn evffect +SAMPLE_OBJECT *munch; + +// apple position +float apple_x = 200, apple_y = 200; + +// player position +float player_x = 100, player_y = 100; + +// score +int score = 0; + +// rendering function +void draw(void) { + // draw background + simple_blit(bg, canvas(), 0, 0); + + // draw player + draw_sprite(canvas(), man, player_x, player_y); + + // draw the apple + draw_sprite(canvas(), apple, apple_x, apple_y); + + // print out current score + char str[25]; + snprintf(str, 25, "Score: %d", score); + textout(canvas(), font(), str, 10, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1); +} + +// update game logic +void update(void) { + // check for keypresses and move the player accordingly + if (key()[KEY_UP]) player_y -= 4; + if (key()[KEY_DOWN]) player_y += 4; + if (key()[KEY_LEFT]) player_x -= 4; + if (key()[KEY_RIGHT]) player_x += 4; + + // if player is touching the apple... + if (distance(player_x, player_y, apple_x, apple_y) < 20) + { + // play muching sound + play_sample(munch, 1., 1., 0); + + // move apple to a new spot, making it look like it's + // a breand new apple + apple_x = rand16() % (SCREEN_W()-32); + apple_y = rand16() % (SCREEN_H()-32); + + // increase score + score++; + + // log success to console + logmsg("Apple eaten!"); + } +} + +void in_loop(void) { + update(); + draw(); +} + +void when_ready(void) { + loop(in_loop, BPS_TO_TIMER(60)); +} + +int main(void) { + enable_debug("output"); + allegro_init_all("canvas", 640, 480, 0, NULL, 0); + man = load_bmp("data/man.png"); + apple = load_bmp("data/apple.png"); + bg = load_bmp("data/grass.jpg"); + munch = load_sample("data/munch.mp3"); + + ready(when_ready, NULL); + + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/exhello.c b/emscripten/examples/exhello.c new file mode 100644 index 0000000..7c0e5b3 --- /dev/null +++ b/emscripten/examples/exhello.c @@ -0,0 +1,18 @@ +#include + +int main(void) { + // Initialising allegro.js + allegro_init(); + + // Selecting canvas element adn setting it up for display at 640x480 + set_gfx_mode("canvas", 640, 480, 1); + + // Clears the screen to white + clear_to_color(canvas(), makecol(255, 255, 255, 255)); + + // Typoes 'Hello World!' message to the centre of the screen + textout_centre(canvas(), font(), "Hello World!", SCREEN_W()/2, SCREEN_H()/2, 24, makecol(0, 0, 0, 255), 0, 0); + + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/extouch.c b/emscripten/examples/extouch.c new file mode 100755 index 0000000..50c4691 --- /dev/null +++ b/emscripten/examples/extouch.c @@ -0,0 +1,35 @@ +#include +#include + +BITMAP_OBJECT *clouds, *ball; + +void draw(void) { + clear_to_color(canvas(), makecol(255, 255, 255, 255)); + stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H()); + + int touch_len; + TOUCH_OBJECT *touchp = touch(&touch_len); + for (int c=0; c +#include +#include + +#define SPRITE_MAX 65536 + +int num = 0, speed = 3; +float x[SPRITE_MAX], y[SPRITE_MAX], vx[SPRITE_MAX], vy[SPRITE_MAX]; +long last_time = 0; +BITMAP_OBJECT *bmp, *buffer; + +void in_loop(void) { + clear_to_color(buffer, makecol(255,255,255,255)); + + for(int c=0; c SCREEN_W()) vx[c] = -abs(vx[c]); + if (y[c]+vy[c] > SCREEN_H()) vy[c] = -abs(vy[c]); + if (x[c]+vx[c] < -64) vx[c] = abs(vx[c]); + if (y[c]+vy[c] < -64) vy[c] = abs(vy[c]); + x[c] += vx[c]; + y[c] += vy[c]; + } + + if (num < SPRITE_MAX) { + x[num] = rand16() % SCREEN_W(); + y[num] = rand16() % SCREEN_H(); + vx[num] = frand()*2 -1; + vy[num] = frand()*2 -1; + num++; + } + long msec = (altime()-last_time)-1; + + char str[256]; + snprintf(str, 256, "Sprites: %d took %ld msec ( %ld fps)", num, msec, 1000/msec); + textout(canvas(), font(), str, 20, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1); + + last_time = altime(); +} + +void when_ready(void) { + loop(in_loop, MSEC_TO_TIMER(1)); +} + +int main(void) { + enable_debug("output"); + set_gfx_mode("canvas", 640, 480, 1); + bmp = load_bmp("data/planet.png"); + buffer = create_bitmap(SCREEN_W(), SCREEN_H()); + ready(when_ready, NULL); + + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/stress.c b/emscripten/examples/stress.c new file mode 100644 index 0000000..e745fdb --- /dev/null +++ b/emscripten/examples/stress.c @@ -0,0 +1,53 @@ +#include +#include +#include + +#define SPRITE_MAX 65536 + +int num = 0, speed = 3; +float x[SPRITE_MAX], y[SPRITE_MAX], vx[SPRITE_MAX], vy[SPRITE_MAX]; +long last_time = 0; +BITMAP_OBJECT *bmp; + +void in_loop(void) { + clear_to_color(canvas(), makecol(255,255,255,255)); + + for(int c=0; c SCREEN_W()) vx[c] = -abs(vx[c]); + if (y[c]+vy[c] > SCREEN_H()) vy[c] = -abs(vy[c]); + if (x[c]+vx[c] < -64) vx[c] = abs(vx[c]); + if (y[c]+vy[c] < -64) vy[c] = abs(vy[c]); + x[c] += vx[c]; + y[c] += vy[c]; + } + + if (num < SPRITE_MAX) { + x[num] = rand16() % SCREEN_W(); + y[num] = rand16() % SCREEN_H(); + vx[num] = frand()*2 -1; + vy[num] = frand()*2 -1; + num++; + } + long msec = (altime()-last_time)-1; + + char str[256]; + snprintf(str, 256, "Sprites: %d took %ld msec ( %ld fps)", num, msec, 1000/msec); + textout(canvas(), font(), str, 20, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1); + + last_time = altime(); +} + +void when_ready(void) { + loop(in_loop, MSEC_TO_TIMER(1)); +} + +int main(void) { + enable_debug("output"); + set_gfx_mode("canvas", 640, 480, 1); + bmp = load_bmp("data/planet.png"); + + ready(when_ready, NULL); + return 0; +} +END_OF_MAIN() diff --git a/emscripten/examples/unittest.c b/emscripten/examples/unittest.c new file mode 100644 index 0000000..001aac3 --- /dev/null +++ b/emscripten/examples/unittest.c @@ -0,0 +1,266 @@ +#include +#include +#include + +BITMAP_OBJECT *clouds, *ball; +SAMPLE_OBJECT *beep; + +int stage = -1; +float delay = 0; +char *title = "allegro.js test"; +const char *subtitle = "press space"; + +int timercolor; +int timers = 0; +int width = 13; + +void callback1(void) { + circlefill(canvas(), 100, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void callback2(void) { + circlefill(canvas(), 200, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void callback3(void) { + circlefill(canvas(), 300, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void callback4(void) { + circlefill(canvas(), 400, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void callback5(void) { + circlefill(canvas(), 500, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void sound_callback(void) { + play_sample(beep, frand(), frand()+.5, 0); + circlefill(canvas(), SCREEN_W()/2, SCREEN_H()/2, 200, makecol(rand16()%255, rand16()%255, rand16()%255, 255)); +} + +void draw(void) { + + if (stage==0) { + title = "progress_bar"; + loading_bar(delay/200.); + } + else if (stage==1) { + title = "blit"; + blit(ball, canvas(), 0, 0, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w+1, rand16()%ball->h+1); + } + else if (stage==2) { + title = "stretch_blit"; + stretch_blit(ball, canvas(), 0, 0, rand16()%ball->w+1, rand16()%ball->h+1, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W()+1, rand16()%SCREEN_H()+1); + } + else if (stage==3) { + title = "draw_sprite"; + draw_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H()); + } + else if (stage==4) { + title = "scaled_sprite"; + scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), frand()*2+.1, frand()*2+.1); + } + else if (stage==5) { + title = "rotate_sprite"; + rotate_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%360); + } + else if (stage==6) { + title = "pivot_sprite"; + pivot_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w, rand16()%ball->h, rand16()%360); + } + else if (stage==7) { + title = "rotate_scaled_sprite"; + rotate_scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%360, frand()*2+.1, frand()*2+.1); + } + else if (stage==8) { + title = "pivot_scaled_sprite"; + pivot_scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w, rand16()%ball->h, rand16()%360, frand()*2+.1, frand()*2+.1); + } + else if (stage==9) { + title = "textout"; + textout(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5); + } + else if (stage==10) { + title = "textout_centre"; + textout_centre(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5); + } + else if (stage==11) { + title = "textout_right"; + textout_right(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5); + } + else if (stage==12) { + title = "getpixel"; + int x = rand16()%SCREEN_W(); + int y = rand16()%SCREEN_H(); + char str[16]; + snprintf(str, 16, "%d", getpixel(canvas(), x, y)); + textout(canvas(), font(), str, x, y, 24, getpixel(canvas(), x, y), 0, 0); + } + else if (stage==13) { + title = "putpixel"; + putpixel(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255)); + } + else if (stage==14) { + title = "clear_to_color"; + clear_to_color(canvas(), makecol(rand16()%255, rand16()%255, rand16()%255, 255)); + } + else if (stage==15) { + title = "line"; + line(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8); + } + else if (stage==16) { + title = "vline"; + vline(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8); + } + else if (stage==17) { + title = "hline"; + hline(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8); + } + else if (stage==18) { + title = "triangle"; + triangle(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8); + } + else if (stage==19) { + title = "trianglefill"; + trianglefill(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255)); + } + else if (stage==20) { + title = "polygon"; + int n = rand16()%10+3; + int p[30]; + for (int c=0; c>3)*24, (c&0xf)*24, 20, 20, makecol(255, 255, 255, 255)); + } + else if (released()[c]) { + rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(255, 255, 0, 255)); + } + else if (key()[c]) { + rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(255, 0, 0, 255)); + } + else { + rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(0, 0, 0, 255)); + } + } + } + else if (stage==30) { + title = "timer"; + stage=31; + timers=1; + install_int_ex(callback1, SECS_TO_TIMER(1)); + install_int_ex(callback2, MSEC_TO_TIMER(500)); + install_int_ex(callback3, BPS_TO_TIMER(3)); + install_int_ex(callback4, BPM_TO_TIMER(60)); + install_int(callback5, 1500); + } + else if (stage==31) { + title = "timer"; + } + else if (stage==32) { + stage=33; + title = "sound"; + remove_all_ints(); + install_int_ex(sound_callback, SECS_TO_TIMER(2)); + } + else if (stage==33) { + title = "sound"; + } + else if (stage==34) { + title = "The End"; + remove_all_ints(); + stage++; + } + + textout_centre(canvas(), font(), title, SCREEN_W()/2, 64, 64, makecol(255, 255, 255, 255), makecol(0, 0, 0, 255), 2); + textout(canvas(), font(), subtitle, 10, SCREEN_H()-10, 24, makecol(255, 255, 255, 255), makecol(0, 0, 0, 255), 1); + delay++; + if (key()[KEY_SPACE] && delay>10) + { + stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H()); + stage++; + delay=0; + } +} + +void in_loop(void) { + draw(); +} + +void when_ready(void) { + stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H()); + loop(in_loop, BPS_TO_TIMER(60)); +} + +int main(void) { + enable_debug("output"); + allegro_init_all("canvas", 640, 480, 0, NULL, 0); + timercolor = makecol(192, 168, 1, 254); + clouds = load_bmp("data/clouds.png"); + ball = load_bmp("data/planet.png"); + beep = load_sample("data/dtmf.mp3"); + + ready(when_ready, NULL); + return 0; +} +END_OF_MAIN() diff --git a/emscripten/library.js b/emscripten/library.js new file mode 100755 index 0000000..6a32698 --- /dev/null +++ b/emscripten/library.js @@ -0,0 +1,451 @@ +/** + You must concatenate allegro.js and this file before you try to use + this file as an emscripten JS library. + cat ../allegro.js > lib.js && cat library.js >> lib.js + + I'm an emscripten library, the “glue” code between C and JS +**/ + +var AllegroJS = { + // PRIVATE STUFF + $ALLEG: { + // HANDLERS + // Index 0 is reserved for default values + bitmaps: [null], + bitmap_addrs: [null], + samples: [null], + fonts: [null], + // POINTER TO CANVAS + canvas: null, + // C ARRAY POINTERS + key: null, + pressed: null, + released: null, + touch: null, + touch_pressed: null, + touch_released: null, + + // PRIVATE FUNCTIONS + // Writes `array`(array of integers) to memory at address `buffer` + writeArray32ToMemory: function(array, buffer) { + for (var i=0; i>2)] = array[i]; + } + }, + // Reads `length` integers from memory at address `buffer` + ReadArray32FromMemory: function(buffer, length) { + var res = []; + for (var i=0; i>2)]); + } + return res; + }, + // Creates C arrays storing key statuses + post_install_keyboard: function() { + ALLEG.key = _malloc(4 * key.length); + ALLEG.pressed = _malloc(4 * pressed.length); + ALLEG.released = _malloc(4 * released.length); + }, + // Creates C arrays storing touch structures + post_install_touch: function() { + // limitation: maximum 32 touch object + ALLEG.touch = _malloc(4*11*32); + ALLEG.touch_pressed = _malloc(4*11*32); + ALLEG.touch_released = _malloc(4*11*32); + }, + // Deletes C arrays storing key statuses + post_remove_keyboard: function() { + _free(ALLEG.key); + _free(ALLEG.pressed); + _free(ALLEG.released); + ALLEG.key = null; + ALLEG.pressed = null; + ALLEG.released = null; + }, + // Deletes C arrays storing touch structures + post_remove_touch: function() { + _free(ALLEG.touch); + _free(ALLEG.touch_pressed); + _free(ALLEG.touch_released); + ALLEG.touch = null; + ALLEG.touch_pressed = null; + ALLEG.touch_released = null; + }, + // Writes JS key arrays to C memory + copy_key_statuses: function() { + ALLEG.writeArray32ToMemory(key, ALLEG.key); + ALLEG.writeArray32ToMemory(pressed, ALLEG.pressed); + ALLEG.writeArray32ToMemory(released, ALLEG.released); + }, + // Writes JS touch arrays to C memory + copy_touch_structs: function() { + var write_touch_array = function(array, buffer) { + for (var i=0; (i>2)] = array[i].x; + HEAP32[((buffer + i*11*4 + 4)>>2)] = array[i].y; + HEAP32[((buffer + i*11*4 + 2*4)>>2)] = array[i].mx; + HEAP32[((buffer + i*11*4 + 3*4)>>2)] = array[i].my; + HEAP32[((buffer + i*11*4 + 4*4)>>2)] = array[i].px; + HEAP32[((buffer + i*11*4 + 5*4)>>2)] = array[i].py; + HEAP32[((buffer + i*11*4 + 6*4)>>2)] = array[i].sx; + HEAP32[((buffer + i*11*4 + 7*4)>>2)] = array[i].sy; + HEAP32[((buffer + i*11*4 + 8*4)>>2)] = array[i].id; + HEAP32[((buffer + i*11*4 + 9*4)>>2)] = array[i].age; + HEAP32[((buffer + i*11*4 + 10*4)>>2)] = array[i].dead; + } + }; + write_touch_array(touch, ALLEG.touch); + write_touch_array(touch_pressed, ALLEG.touch_pressed); + write_touch_array(touch_released, ALLEG.touch_released); + }, + // Creates `canvas` and `font` C globals + post_set_gfx_mode: function() { + ALLEG.bitmaps[0] = canvas; + ALLEG.fonts[0] = font; + ALLEG.canvas = ALLEG.alloc_pack_bitmap(0); + }, + // Stores bitmap infomations in a C bitmap struct + pack_bitmap: function(handle) { + var addr = ALLEG.bitmap_addrs[handle]; + setValue(addr, handle, "i32"); + setValue(addr+4, ALLEG.bitmaps[handle].w, "i32"); + setValue(addr+8, ALLEG.bitmaps[handle].h, "i32"); + }, + // Allocates and packs a bitmap for C + alloc_pack_bitmap: function(handle) { + var res = _malloc(3*4); + ALLEG.bitmap_addrs[handle] = res; + ALLEG.pack_bitmap(handle); + return res; + }, + // Repacks every bitmaps (because bitmap loading is asynchronous) called by _ready + repack_bitmaps: function() { + for (var it=1; it + + + allegro.js examples + + + + + + +

allegro.js touch example

+ +
+ Download source! + + \ No newline at end of file diff --git a/examples/extouch.js b/examples/extouch.js new file mode 100755 index 0000000..5c462cc --- /dev/null +++ b/examples/extouch.js @@ -0,0 +1,33 @@ +var clouds,ball; + +function draw() +{ + clear_to_color(canvas, makecol(255, 255, 255)); + stretch_blit(clouds,canvas,0,0,clouds.w,clouds.h,0,0,SCREEN_W,SCREEN_H); + + for (var c=0; c