diff --git a/project/jni/application/ballfield/AndroidAppSettings.cfg b/project/jni/application/ballfield/AndroidAppSettings.cfg new file mode 100644 index 000000000..740905c36 --- /dev/null +++ b/project/jni/application/ballfield/AndroidAppSettings.cfg @@ -0,0 +1,30 @@ +# The application settings for Android libSDL port +AppSettingVersion=12 +LibSdlVersion=1.2 +AppName="Ballfield" +AppFullName=net.olofson.ballfield +ScreenOrientation=h +InhibitSuspend=n +AppDataDownloadUrl="Game data is 1 Mb|ballfield.zip" +SdlVideoResize=y +SdlVideoResizeKeepAspect=n +NeedDepthBuffer=n +AppUsesMouse=n +AppNeedsArrowKeys=n +AppUsesJoystick=n +AppHandlesJoystickSensitivity=n +AppUsesMultitouch=n +NonBlockingSwapBuffers=n +RedefinedKeys="SPACE RETURN" +AppTouchscreenKeyboardKeysAmount=1 +AppTouchscreenKeyboardKeysAmountAutoFire=0 +MultiABI=n +AppVersionCode=101 +AppVersionName="1.01" +CompiledLibraries="sdl_mixer sdl_image" +CustomBuildScript=n +AppCflags='-O2 -finline-functions' +AppLdflags='' +AppSubdirsBuild='' +AppUseCrystaXToolchain=n +ReadmeText='^' diff --git a/project/jni/application/ballfield/AndroidData/ballfield.zip b/project/jni/application/ballfield/AndroidData/ballfield.zip new file mode 100644 index 000000000..3d65c19da Binary files /dev/null and b/project/jni/application/ballfield/AndroidData/ballfield.zip differ diff --git a/project/jni/application/ballfield/ballfield.c b/project/jni/application/ballfield/ballfield.c new file mode 100644 index 000000000..ee57f1c3c --- /dev/null +++ b/project/jni/application/ballfield/ballfield.c @@ -0,0 +1,515 @@ +/* + * "Ballfield" + * + * (C) David Olofson , 2002, 2003 + * + * This software is released under the terms of the GPL. + * + * Contact author for permission if you want to use this + * software, or work derived from it, under other terms. + */ + +#include +#include +#include + +#include "SDL.h" +#include "SDL_image.h" + +#include "ballfield.h" + + +/*---------------------------------------------------------- + General tool functions +----------------------------------------------------------*/ + +/* + * Bump areas of low and high alpha to 0% or 100% + * respectively, just in case the graphics contains + * "alpha noise". + */ +SDL_Surface *clean_alpha(SDL_Surface *s) +{ + SDL_Surface *work; + SDL_Rect r; + Uint32 *pixels; + int pp; + int x, y; + + work = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, + 32, 0xff000000, 0x00ff0000, 0x0000ff00, + 0x000000ff); + if(!work) + return NULL; + + r.x = r.y = 0; + r.w = s->w; + r.h = s->h; + if(SDL_BlitSurface(s, &r, work, NULL) < 0) + { + SDL_FreeSurface(work); + return NULL; + } + + SDL_LockSurface(work); + pixels = work->pixels; + pp = work->pitch / sizeof(Uint32); + for(y = 0; y < work->h; ++y) + for(x = 0; x < work->w; ++x) + { + Uint32 pix = pixels[y*pp + x]; + switch((pix & 0xff) >> 4) + { + case 0: + pix = 0x00000000; + break; + default: + break; + case 15: + pix |= 0xff; + break; + } + pixels[y*pp + x] = pix; + } + SDL_UnlockSurface(work); + + return work; +} + + +/* + * Load and convert an antialiazed, zoomed set of sprites. + */ +SDL_Surface *load_zoomed(char *name, int alpha) +{ + SDL_Surface *sprites; + SDL_Surface *temp = IMG_Load(name); + if(!temp) + return NULL; + + /* + sprites = temp; + SDL_SetAlpha(sprites, 0, 255); + temp = clean_alpha(sprites); + SDL_FreeSurface(sprites); + */ + if(!temp) + { + fprintf(stderr, "Could not clean alpha!\n"); + return NULL; + } + + if(alpha) + { + SDL_SetAlpha(temp, 0, SDL_ALPHA_OPAQUE); + sprites = SDL_DisplayFormatAlpha(temp); + } + else + { + SDL_SetColorKey(temp, SDL_SRCCOLORKEY, + SDL_MapRGB(temp->format, 0, 0, 0)); + sprites = SDL_DisplayFormat(temp); + } + SDL_FreeSurface(temp); + + return sprites; +} + + +void print_num(SDL_Surface *dst, SDL_Surface *font, int x, int y, float value) +{ + char buf[16]; + int val = (int)(value * 10.0); + int pos, p = 0; + SDL_Rect from; + + /* Sign */ + if(val < 0) + { + buf[p++] = 10; + val = -val; + } + + /* Integer part */ + pos = 10000000; + while(pos > 1) + { + int num = val / pos; + val -= num * pos; + pos /= 10; + if(p || num) + buf[p++] = num; + } + + /* Decimals */ + if(val / pos) + { + buf[p++] = 11; + while(pos > 0) + { + int num = val / pos; + val -= num * pos; + pos /= 10; + buf[p++] = num; + } + } + + /* Render! */ + from.y = 0; + from.w = 7; + from.h = 10; + for(pos = 0; pos < p; ++pos) + { + SDL_Rect to; + to.x = x + pos * 7; + to.y = y; + from.x = buf[pos] * 7; + SDL_BlitSurface(font, &from, dst, &to); + } +} + + + +/*---------------------------------------------------------- + ballfield_t functions +----------------------------------------------------------*/ + +ballfield_t *ballfield_init(void) +{ + int i; + ballfield_t *bf = calloc(sizeof(ballfield_t), 1); + if(!bf) + return NULL; + for(i = 0; i < BALLS; ++i) + { + bf->points[i].x = rand() % 0x20000; + bf->points[i].y = rand() % 0x20000; + bf->points[i].z = 0x20000 * i / BALLS; + if(rand() % 100 > 80) + bf->points[i].c = 1; + else + bf->points[i].c = 0; + } + return bf; +} + + +void ballfield_free(ballfield_t *bf) +{ + int i; + for(i = 0; i < COLORS; ++i) + SDL_FreeSurface(bf->gfx[i]); +} + + +static int ballfield_init_frames(ballfield_t *bf) +{ + int i, j; + /* + * Set up source rects for all frames + */ + bf->frames = calloc(sizeof(SDL_Rect), bf->gfx[0]->w); + if(!bf->frames) + { + fprintf(stderr, "No memory for frame rects!\n"); + return -1; + } + for(j = 0, i = 0; i < bf->gfx[0]->w; ++i) + { + bf->frames[i].x = 0; + bf->frames[i].y = j; + bf->frames[i].w = bf->gfx[0]->w - i; + bf->frames[i].h = bf->gfx[0]->w - i; + j += bf->gfx[0]->w - i; + } + return 0; +} + + +int ballfield_load_gfx(ballfield_t *bf, char *name, unsigned int color) +{ + if(color >= COLORS) + return -1; + + bf->gfx[color] = load_zoomed(name, bf->use_alpha); + if(!bf->gfx[color]) + return -2; + + if(!bf->frames) + return ballfield_init_frames(bf); + + return 0; +} + + +void ballfield_move(ballfield_t *bf, Sint32 dx, Sint32 dy, Sint32 dz) +{ + int i; + for(i = 0; i < BALLS; ++i) + { + bf->points[i].x += dx; + bf->points[i].x &= 0x1ffff; + bf->points[i].y += dy; + bf->points[i].y &= 0x1ffff; + bf->points[i].z += dz; + bf->points[i].z &= 0x1ffff; + } +} + + +void ballfield_render(ballfield_t *bf, SDL_Surface *screen) +{ + int i, j, z; + + /* + * Find the ball with the highest Z. + */ + z = 0; + j = 0; + for(i = 0; i < BALLS; ++i) + { + if(bf->points[i].z > z) + { + j = i; + z = bf->points[i].z; + } + } + + /* + * Render all balls in back->front order. + */ + for(i = 0; i < BALLS; ++i) + { + SDL_Rect r; + int f; + z = bf->points[j].z; + z += 50; + f = ((bf->frames[0].w << 12) + 100000) / z; + f = bf->frames[0].w - f; + if(f < 0) + f = 0; + else if(f > bf->frames[0].w - 1) + f = bf->frames[0].w - 1; + z >>= 7; + z += 1; + r.x = (bf->points[j].x - 0x10000) / z; + r.y = (bf->points[j].y - 0x10000) / z; + r.x += (screen->w - bf->frames[f].w) >> 1; + r.y += (screen->h - bf->frames[f].h) >> 1; + SDL_BlitSurface(bf->gfx[bf->points[j].c], + &bf->frames[f], screen, &r); + if(--j < 0) + j = BALLS - 1; + } +} + + + +/*---------------------------------------------------------- + Other rendering functions +----------------------------------------------------------*/ + +/* + * Draw tiled background image with offset. + */ +void tiled_back(SDL_Surface *back, SDL_Surface *screen, int xo, int yo) +{ + int x, y; + SDL_Rect r; + if(xo < 0) + xo += back->w*(-xo/back->w + 1); + if(yo < 0) + yo += back->h*(-yo/back->h + 1); + xo %= back->w; + yo %= back->h; + for(y = -yo; y < screen->h; y += back->h) + for(x = -xo; x < screen->w; x += back->w) + { + r.x = x; + r.y = y; + SDL_BlitSurface(back, NULL, screen, &r); + } +} + + + +/*---------------------------------------------------------- + main() +----------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + ballfield_t *balls; + SDL_Surface *screen; + SDL_Surface *temp_image; + SDL_Surface *back, *logo, *font; + SDL_Event event; + int bpp = 16, + flags = SDL_DOUBLEBUF | SDL_HWSURFACE, + alpha = 1; + int x_offs = 0, y_offs = 0; + long tick, + last_tick, + last_avg_tick; + double t = 0; + float dt; + int i; + float fps = 0.0; + int fps_count = 0; + int fps_start = 0; + float x_speed, y_speed, z_speed; + + SDL_Init(SDL_INIT_VIDEO); + + atexit(SDL_Quit); + + for(i = 1; i < argc; ++i) + { + if(strncmp(argv[i], "-na", 3) == 0) + alpha = 0; + else if(strncmp(argv[i], "-nd", 3) == 0) + flags &= ~SDL_DOUBLEBUF; + else if(strncmp(argv[i], "-h", 2) == 0) + { + flags |= SDL_HWSURFACE; + flags &= ~SDL_SWSURFACE; + } + else if(strncmp(argv[i], "-f", 2) == 0) + flags |= SDL_FULLSCREEN; + else + bpp = atoi(&argv[i][1]); + } + + screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, bpp, flags); + if(!screen) + { + fprintf(stderr, "Failed to open screen!\n"); + exit(-1); + } + + SDL_WM_SetCaption("Ballfield", "Ballfield"); + if(flags & SDL_FULLSCREEN) + SDL_ShowCursor(0); + + balls = ballfield_init(); + if(!balls) + { + fprintf(stderr, "Failed to create ballfield!\n"); + exit(-1); + } + + /* + * Load and prepare balls... + */ + balls->use_alpha = alpha; + if( ballfield_load_gfx(balls, "blueball.png", 0) + || + ballfield_load_gfx(balls, "redball.png", 1) ) + { + fprintf(stderr, "Could not load balls!\n"); + exit(-1); + } + + /* + * Load background image + */ + temp_image = IMG_Load("redbluestars.png"); + if(!temp_image) + { + fprintf(stderr, "Could not load background!\n"); + exit(-1); + } + back = SDL_DisplayFormat(temp_image); + SDL_FreeSurface(temp_image); + + /* + * Load logo + */ + temp_image = SDL_LoadBMP("logo.bmp"); + if(!temp_image) + { + fprintf(stderr, "Could not load logo!\n"); + exit(-1); + } + SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY|SDL_RLEACCEL, + SDL_MapRGB(temp_image->format, 255, 0, 255)); + logo = SDL_DisplayFormat(temp_image); + SDL_FreeSurface(temp_image); + + /* + * Load font + */ + temp_image = SDL_LoadBMP("font7x10.bmp"); + if(!temp_image) + { + fprintf(stderr, "Could not load font!\n"); + exit(-1); + } + SDL_SetColorKey(temp_image, SDL_SRCCOLORKEY|SDL_RLEACCEL, + SDL_MapRGB(temp_image->format, 255, 0, 255)); + font = SDL_DisplayFormat(temp_image); + SDL_FreeSurface(temp_image); + + last_avg_tick = last_tick = SDL_GetTicks(); + while(1) + { + SDL_Rect r; + if(SDL_PollEvent(&event) > 0) + { + if(event.type == SDL_MOUSEBUTTONDOWN) + break; + + if(event.type & (SDL_KEYUP | SDL_KEYDOWN)) + { + Uint8 *keys = SDL_GetKeyState(&i); + if(keys[SDLK_ESCAPE]) + break; + } + } + + /* Timing */ + tick = SDL_GetTicks(); + dt = (tick - last_tick) * 0.001f; + last_tick = tick; + + /* Background image */ + tiled_back(back, screen, x_offs>>11, y_offs>>11); + + /* Ballfield */ + ballfield_render(balls, screen); + + /* Logo */ + r.x = 2; + r.y = 2; + SDL_BlitSurface(logo, NULL, screen, &r); + + /* FPS counter */ + if(tick > fps_start + 500) + { + fps = (float)fps_count * 1000.0 / (tick - fps_start); + fps_count = 0; + fps_start = tick; + } + print_num(screen, font, screen->w-37, screen->h-12, fps); + ++fps_count; + + SDL_Flip(screen); + + /* Animate */ + x_speed = 500.0 * sin(t * 0.37); + y_speed = 500.0 * sin(t * 0.53); + z_speed = 400.0 * sin(t * 0.21); + + ballfield_move(balls, x_speed, y_speed, z_speed); + x_offs -= x_speed; + y_offs -= y_speed; + + t += dt; + } + + ballfield_free(balls); + SDL_FreeSurface(back); + SDL_FreeSurface(logo); + SDL_FreeSurface(font); + exit(0); +} diff --git a/project/jni/application/ballfield/ballfield.h b/project/jni/application/ballfield/ballfield.h new file mode 100644 index 000000000..cd71af62f --- /dev/null +++ b/project/jni/application/ballfield/ballfield.h @@ -0,0 +1,61 @@ +/* + * "Ballfield" + * + * (C) David Olofson , 2002 + * + * This software is released under the terms of the GPL. + * + * Contact author for permission if you want to use this + * software, or work derived from it, under other terms. + */ + +#ifndef _BALLFIELD_H_ +#define _BALLFIELD_H_ + +#include "SDL.h" + +/*---------------------------------------------------------- + Definitions... +----------------------------------------------------------*/ + +#define BALLS 200 + +#define COLORS 2 + +typedef struct +{ + Sint32 x, y, z; /* Position */ + Uint32 c; /* Color */ +} point_t; + + +/* + * Ballfield + */ +typedef struct +{ + point_t points[BALLS]; + SDL_Rect *frames; + SDL_Surface *gfx[COLORS]; + int use_alpha; +} ballfield_t; + + +/* + * Size of the screen in pixels + */ +#define SCREEN_W 320 +#define SCREEN_H 240 + +/* + * Size of the biggest ball image in pixels + * + * Balls are scaled down and *packed*, one pixel + * smaller for each frame down to 1x1. The actual + * image width is (obviously...) the same as the + * width of the first frame. + */ +#define BALL_W 32 +#define BALL_H 32 + +#endif /* _BALLFIELD_H_ */ diff --git a/project/jni/application/ballfield/icon.png b/project/jni/application/ballfield/icon.png new file mode 100644 index 000000000..b3614e149 Binary files /dev/null and b/project/jni/application/ballfield/icon.png differ