commit e75581fa7828f78cca582d4b26032f5029250f86 Author: Massive Box <71317968+MassiveBox@users.noreply.github.com> Date: Thu Jul 1 14:49:46 2021 +0000 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b2b7ce1 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC := gcc +CFLAGS := `sdl-config --libs --cflags` -ggdb3 -O0 --std=c99 -Wall -lSDL_image -lSDL_mixer -lm +HDRS := +SRCS := src/main.c src/match.c src/graphics.c src/logic.c src/keys.c src/audio.c +OBJS := $(SRCS:.c=.o) + +EXEC := jiljil.dge + +all: $(EXEC) + +$(EXEC): $(OBJS) $(HDRS) Makefile + $(CC) -o $@ $(OBJS) $(CFLAGS) + +clean: + rm -f $(EXEC) $(OBJS) + +.PHONY: all clean diff --git a/Makefile.RS97 b/Makefile.RS97 new file mode 100644 index 0000000..af6ac1e --- /dev/null +++ b/Makefile.RS97 @@ -0,0 +1,20 @@ +CC := mipsel-linux-gcc +CFLAGS := `sdl-config --libs --cflags` -ggdb3 -O0 --std=c99 -Wall -lSDL_image -lSDL_mixer -lm +HDRS := +SRCS := src/main.c src/match.c src/graphics.c src/logic.c src/keys.c src/audio.c +OBJS := $(SRCS:.c=.o) + +EXEC := jiljil.dge + +all: $(EXEC) + +$(EXEC): $(OBJS) $(HDRS) Makefile + $(CC) -o $@ $(OBJS) $(CFLAGS) + cp ./jiljil.dge ./ipk/data/home/retrofw/games/jiljil-c/jiljil.dge + cp -r assets ./ipk/data/home/retrofw/games/jiljil-c/assets/ + ./ipk/create-ipk.sh + +clean: + rm -f $(EXEC) $(OBJS) + +.PHONY: all clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..416e0c8 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# RetroFW JilJil + +![1](https://telegra.ph/file/3402cbb5a0065adee1f4f.jpg)![2](https://telegra.ph/file/51443278b9b2e4f8213f5.jpg)![3](https://telegra.ph/file/fc95a25bf190d0b726c1e.jpg) + +This repo contains the source code for my port of [JilJil](https://www.cavestory.org/pixels-works/jil-jil.php) for (hopefully) **RetroFW** compatible devices and **Linux**. + +JilJil is a simple **arcade-style** score based game, where you control a weird **worm** inside an aquarium, and you have to run away from a **cat** that is trying to catch you by the ribbon on your tail. You also have to bounce off of a **lemon** as many times as you can. + +While this game is named as a port of JilJil, the actual source code of JilJil is not publicly available, so I decided to rewrite the game from scratch and I've added some tweaks here and there to spice up the gameplay. The physics are not supposed to be 1:1 to actual JilJil! + +Some of the assets and resources used to create this game are (c) 1997 Studio Pixel. If you represent mr. Daisuke Amaya, Studio Pixel, or any affiliates, please contact me at legal@massivebox.eu.org. + +## Make-ing + +### For Linux + +Simply run `make`. +You'll need `SDL` development libraries (including SDL Mixer and SDL Image), and the C compiler `gcc`. +You will get an executable called `2048.dge`, run it and enjoy your 2048 experience! + +### For RetroFW + +Run `make -f Makefile.RS97` +You'll need a [working buildroot installation](https://github.com/retrofw/retrofw.github.io/wiki/Configuring-a-Toolchain), that includes the SDL development libraries, and `gcc`. Since RetroFW runs on MIPSel devices, instead of the compiler `gcc`, the Makefile will use `mipsel-linux-gcc`, make sure it is a working command on your machine, if it isn't, make sure that the folder where the `mipsel-linux-gcc` binary is stored is in `$PATH`. +You will get a file called `build.ipk` that you can [install](https://github.com/retrofw/retrofw.github.io/wiki/Emulators-and-Apps#install-ipk) on RetroFW devices. + +### For Windows + +I have no idea. Just get Linux :P + +## Contributing + +Contributions are always welcome! You can contribute by opening a pull request or an issue. +You can also report me stuff via email if you don't want to sign up to whichever Git server I choose to host this project. +My mail is hello@massivebox.eu.org. + diff --git a/assets/bgm/game_over b/assets/bgm/game_over new file mode 100644 index 0000000..a83fb8c Binary files /dev/null and b/assets/bgm/game_over differ diff --git a/assets/bgm/in_game b/assets/bgm/in_game new file mode 100644 index 0000000..2cb0de8 Binary files /dev/null and b/assets/bgm/in_game differ diff --git a/assets/images/BMP_CHARACTOR.png b/assets/images/BMP_CHARACTOR.png new file mode 100644 index 0000000..d3877bc Binary files /dev/null and b/assets/images/BMP_CHARACTOR.png differ diff --git a/assets/images/JILJIL.png b/assets/images/JILJIL.png new file mode 100644 index 0000000..274fcde Binary files /dev/null and b/assets/images/JILJIL.png differ diff --git a/assets/images/fpsfont.png b/assets/images/fpsfont.png new file mode 100644 index 0000000..3d24933 Binary files /dev/null and b/assets/images/fpsfont.png differ diff --git a/assets/images/icon.png b/assets/images/icon.png new file mode 100644 index 0000000..9ca0f8f Binary files /dev/null and b/assets/images/icon.png differ diff --git a/assets/images/pause.png b/assets/images/pause.png new file mode 100644 index 0000000..c093902 Binary files /dev/null and b/assets/images/pause.png differ diff --git a/assets/sfx/bongo b/assets/sfx/bongo new file mode 100644 index 0000000..c5b81f7 Binary files /dev/null and b/assets/sfx/bongo differ diff --git a/assets/sfx/cat_sound b/assets/sfx/cat_sound new file mode 100644 index 0000000..c5f410b Binary files /dev/null and b/assets/sfx/cat_sound differ diff --git a/assets/sfx/cho b/assets/sfx/cho new file mode 100644 index 0000000..b5762bf Binary files /dev/null and b/assets/sfx/cho differ diff --git a/assets/sfx/clap b/assets/sfx/clap new file mode 100644 index 0000000..c9a60fc Binary files /dev/null and b/assets/sfx/clap differ diff --git a/assets/sfx/cough_cough b/assets/sfx/cough_cough new file mode 100644 index 0000000..5554b02 Binary files /dev/null and b/assets/sfx/cough_cough differ diff --git a/assets/sfx/game_start b/assets/sfx/game_start new file mode 100644 index 0000000..b668784 Binary files /dev/null and b/assets/sfx/game_start differ diff --git a/assets/sfx/inhale b/assets/sfx/inhale new file mode 100644 index 0000000..9176ce9 Binary files /dev/null and b/assets/sfx/inhale differ diff --git a/assets/sfx/reverse b/assets/sfx/reverse new file mode 100644 index 0000000..0a0b554 Binary files /dev/null and b/assets/sfx/reverse differ diff --git a/assets/sfx/ronf b/assets/sfx/ronf new file mode 100644 index 0000000..e9f6ffe Binary files /dev/null and b/assets/sfx/ronf differ diff --git a/assets/sfx/rumble b/assets/sfx/rumble new file mode 100644 index 0000000..b914bf0 Binary files /dev/null and b/assets/sfx/rumble differ diff --git a/assets/sfx/sneeze_long b/assets/sfx/sneeze_long new file mode 100644 index 0000000..45f006c Binary files /dev/null and b/assets/sfx/sneeze_long differ diff --git a/assets/sfx/sneeze_short b/assets/sfx/sneeze_short new file mode 100644 index 0000000..2cea8bc Binary files /dev/null and b/assets/sfx/sneeze_short differ diff --git a/ipk/control/control b/ipk/control/control new file mode 100644 index 0000000..46ec08a --- /dev/null +++ b/ipk/control/control @@ -0,0 +1,11 @@ +Package: jiljil-c +Version: 0.1 +Description: Arcade highscore-based game. +Replaces: jiljil-c +Section: games +Priority: optional +Maintainer: massivebox +Architecture: mipsel +Homepage: https://codeberg.org/massivebox/retrofw-jiljil-c +Depends: +Source: https://codeberg.org/massivebox/retrofw-jiljil-c diff --git a/ipk/create-ipk.sh b/ipk/create-ipk.sh new file mode 100644 index 0000000..637948b --- /dev/null +++ b/ipk/create-ipk.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +cd ipk +cd data && tar cvzf ../data.tar.gz * +cd ../control && tar cvzf ../control.tar.gz * +cd .. && ar rv build.ipk control.tar.gz data.tar.gz debian-binary +rm data.tar.gz control.tar.gz +rm -rf ./data/home/retrofw/games/jiljil-c/assets ./data/home/retrofw/games/jiljil-c/jiljil.dge +mv build.ipk .. \ No newline at end of file diff --git a/ipk/data/home/retrofw/apps/gmenu2x/sections/games/jiljil-c.lnk b/ipk/data/home/retrofw/apps/gmenu2x/sections/games/jiljil-c.lnk new file mode 100644 index 0000000..a50c670 --- /dev/null +++ b/ipk/data/home/retrofw/apps/gmenu2x/sections/games/jiljil-c.lnk @@ -0,0 +1,4 @@ +title=JilJil +description=Arcade highscore-based game. +exec=/home/retrofw/games/jiljil-c/jiljil.dge +clock=600 diff --git a/ipk/data/home/retrofw/games/jiljil-c/jiljil.png b/ipk/data/home/retrofw/games/jiljil-c/jiljil.png new file mode 100644 index 0000000..9ca0f8f Binary files /dev/null and b/ipk/data/home/retrofw/games/jiljil-c/jiljil.png differ diff --git a/ipk/debian-binary b/ipk/debian-binary new file mode 100644 index 0000000..cd5ac03 --- /dev/null +++ b/ipk/debian-binary @@ -0,0 +1 @@ +2.0 diff --git a/src/audio.c b/src/audio.c new file mode 100644 index 0000000..af28041 --- /dev/null +++ b/src/audio.c @@ -0,0 +1,128 @@ +#include "include.h" + +#include "audio.h" + +// sfx +Mix_Chunk *bongo; +Mix_Chunk *cat_sound; +Mix_Chunk *cho; +Mix_Chunk *clap; +Mix_Chunk *cough_cough; +Mix_Chunk *game_start; +Mix_Chunk *inhale; +Mix_Chunk *reverse; +Mix_Chunk *ronf; +Mix_Chunk *rumble; +Mix_Chunk *sneeze_long; +Mix_Chunk *sneeze_short; + +// bgm +Mix_Chunk *game_over; +Mix_Chunk *in_game; + +int bgm_channel = 0; + +void load_audio(void) { + + bongo = Mix_LoadWAV("assets/sfx/bongo"); + cat_sound = Mix_LoadWAV("assets/sfx/cat_sound"); + cho = Mix_LoadWAV("assets/sfx/cho"); + clap = Mix_LoadWAV("assets/sfx/clap"); + cough_cough = Mix_LoadWAV("assets/sfx/cough_cough"); + game_start = Mix_LoadWAV("assets/sfx/game_start"); + inhale = Mix_LoadWAV("assets/sfx/inhale"); + reverse = Mix_LoadWAV("assets/sfx/reverse"); + ronf = Mix_LoadWAV("assets/sfx/ronf"); + rumble = Mix_LoadWAV("assets/sfx/rumble"); + sneeze_long = Mix_LoadWAV("assets/sfx/sneeze_long"); + sneeze_short = Mix_LoadWAV("assets/sfx/sneeze_short"); + + game_over = Mix_LoadWAV("assets/bgm/game_over"); + in_game = Mix_LoadWAV("assets/bgm/in_game"); + +} + +void unload_audio(void) { + + Mix_FreeChunk(bongo); + Mix_FreeChunk(cat_sound); + Mix_FreeChunk(cho); + Mix_FreeChunk(clap); + Mix_FreeChunk(cough_cough); + Mix_FreeChunk(game_start); + Mix_FreeChunk(inhale); + Mix_FreeChunk(reverse); + Mix_FreeChunk(ronf); + Mix_FreeChunk(rumble); + Mix_FreeChunk(sneeze_long); + Mix_FreeChunk(sneeze_short); + + Mix_FreeChunk(game_over); + Mix_FreeChunk(in_game); + +} + +int play_sound_internal(char *name, int loop) { + + Mix_Chunk *sound; + + if(!strcmp(name, "bongo")) { + sound = bongo; + } else if (!strcmp(name, "cat_sound")) { + sound = cat_sound; + } else if (!strcmp(name, "cho")) { + sound = cho; + } else if (!strcmp(name, "clap")) { + sound = clap; + } else if (!strcmp(name, "cough_cough")) { + sound = cough_cough; + } else if (!strcmp(name, "game_start")) { + sound = game_start; + } else if (!strcmp(name, "inhale")) { + sound = inhale; + } else if (!strcmp(name, "reverse")) { + sound = reverse; + } else if (!strcmp(name, "ronf")) { + sound = ronf; + } else if (!strcmp(name, "rumble")) { + sound = rumble; + } else if (!strcmp(name, "sneeze_long")) { + sound = sneeze_long; + } else if (!strcmp(name, "sneeze_short")) { + sound = sneeze_short; + } else if (!strcmp(name, "game_over")) { + sound = game_over; + } else if (!strcmp(name, "in_game")) { + sound = in_game; + } + + return Mix_PlayChannel(-1, sound, loop); + +} + +void play_sound(char *name) { + play_sound_internal(name, 0); +} + +void play_sound_and_wait(char *name) { + int chan = play_sound_internal(name, 0); + int playing = Mix_Playing(chan); + while(playing) { // wait for sound to end + SDL_Delay(50); + playing = Mix_Playing(chan); + } + SDL_Delay(500); +} + +void play_bgm(char *name) { + bgm_channel = play_sound_internal(name, -1); +} +void pause_bgm(void) { + Mix_Pause(bgm_channel); +} +void resume_bgm(void) { + Mix_Resume(bgm_channel); +} +void stop_bgm(void) { + Mix_HaltChannel(bgm_channel); +} \ No newline at end of file diff --git a/src/audio.h b/src/audio.h new file mode 100644 index 0000000..38dbb7b --- /dev/null +++ b/src/audio.h @@ -0,0 +1,10 @@ +void play_sound(char *name); +void play_sound_and_wait(char *name); +void play_bgm(char *name); + +void pause_bgm(void); +void resume_bgm(void); +void stop_bgm(void); + +void load_audio(void); +void unload_audio(void); \ No newline at end of file diff --git a/src/graphics.c b/src/graphics.c new file mode 100644 index 0000000..f32fca9 --- /dev/null +++ b/src/graphics.c @@ -0,0 +1,77 @@ +#include "include.h" + +#include "main.h" + +extern SDL_Surface *tilesIMG; +extern SDL_Surface *fpsFontIMG; + +// load_asset is a helper function to reload assets from a file +SDL_Surface* load_asset(char path[]) { + + SDL_Surface* _img = IMG_Load(path); + SDL_Surface* img = SDL_DisplayFormat(_img); + SDL_FreeSurface(_img); + + return img; + +} + +// print_score draws the specified score on the specified screen at the specified coordinates +void print_score(int score_x, int score_y, int number, SDL_Surface * screen) { + + int n = log10(number) + 1; + int i; + int *numberArray = calloc(n, sizeof(int)); + for ( i = 0; i < n; ++i, number /= 10 ) + { + numberArray[i] = number % 10; + } + + SDL_Rect SrcZero = {x: 0, y: 112, w: 8, h: 16}; + SDL_Rect DstDigitZero = {x: score_x, y: score_y}; + SDL_Rect DstDigitOne = {x: score_x + 8, y: score_y}; + SDL_Rect DstDigitTwo = {x: score_x + 16, y: score_y}; + + if(n == 1) { + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitZero); + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitOne); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[0], y: 112, w: 8, h: 16}, screen, &DstDigitTwo); + } else if(n == 2) { + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitZero); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[0], y: 112, w: 8, h: 16}, screen, &DstDigitTwo); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[1], y: 112, w: 8, h: 16}, screen, &DstDigitOne); + } else if(n == 3) { + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[0], y: 112, w: 8, h: 16}, screen, &DstDigitTwo); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[1], y: 112, w: 8, h: 16}, screen, &DstDigitOne); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 8 * numberArray[2], y: 112, w: 8, h: 16}, screen, &DstDigitZero); + } else { // for zero digits and more than 3 we just show zeroes lol + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitTwo); + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitOne); + SDL_BlitSurface(tilesIMG, &SrcZero, screen, &DstDigitZero); + } + +} + +// clear_screen resets the screen +void clear_screen(SDL_Surface* screen) { + + SDL_FillRect(screen, NULL, 0); + + int row, col; + for (row = 0; row < 2; row++) { + for (col = 0; col < 14; col++) { + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 64, w: 20, h: 20}, screen, &(SDL_Rect){x: 21 + 20*col, y: row*221}); + } + } + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 80, y: 112, w: 17, h: 7}, screen, &(SDL_Rect){x: 208, y: 22}); //Hi + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 80, y: 121, w: 47, h: 7}, screen, &(SDL_Rect){x: 226, y: 22}); //Score + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 80, y: 121, w: 47, h: 7}, screen, &(SDL_Rect){x: 226, y: 213}); //Score + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 95, w: 23, h: 7}, screen, &(SDL_Rect){x: 22, y: 213}); //JpLeft + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 84, w: 65, h: 8}, screen, &(SDL_Rect){x: 49, y: 212}); //JpRight + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 80, y: 16, w: 48, h: 7}, screen, &(SDL_Rect){x: 141, y: 224}); //exit->esc + +} diff --git a/src/graphics.h b/src/graphics.h new file mode 100644 index 0000000..dfa5d70 --- /dev/null +++ b/src/graphics.h @@ -0,0 +1,8 @@ +void clear_screen(SDL_Surface*); +void game_over_animation(SDL_Surface*); +void game_won_animation(SDL_Surface*); +void print_board(SDL_Surface*); +void move_board(int, SDL_Surface*); +void print_score(int, int, int, SDL_Surface*); + +SDL_Surface* load_asset(char path[]); diff --git a/src/include.h b/src/include.h new file mode 100644 index 0000000..38bcd7b --- /dev/null +++ b/src/include.h @@ -0,0 +1,11 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "SDL/SDL_mixer.h" +#include "SDL/SDL_sound.h" \ No newline at end of file diff --git a/src/keys.c b/src/keys.c new file mode 100644 index 0000000..28cf32b --- /dev/null +++ b/src/keys.c @@ -0,0 +1,37 @@ +#include "include.h" + +int internal_keycode_from_sdl(int sdl_keycode) { + + /* + invalid = -1 + up = 0 + right = 1 + down = 2 + left = 3 + start = 4 + select = 5 + */ + + + switch(sdl_keycode) { + case SDLK_ESCAPE: //Select + return 5; + case SDLK_RETURN: + return 4; + case SDLK_LCTRL: // A button + case SDLK_RIGHT: // right + return 1; + case SDLK_LSHIFT: // Y button + case SDLK_LEFT: // left + return 3; + case SDLK_LALT: // B button + case SDLK_DOWN: // down + return 2; + case SDLK_SPACE: // X button + case SDLK_UP: // up + return 0; + default: + return -1; + } + +} diff --git a/src/keys.h b/src/keys.h new file mode 100644 index 0000000..83530e9 --- /dev/null +++ b/src/keys.h @@ -0,0 +1 @@ +int internal_keycode_from_sdl(int); \ No newline at end of file diff --git a/src/logic.c b/src/logic.c new file mode 100644 index 0000000..945b960 --- /dev/null +++ b/src/logic.c @@ -0,0 +1,135 @@ +#include "include.h" + +// get_best_score_from_file loads the best saved score from best_score.txt and puts it to best_score +int get_best_score_from_file(void) { + + if(access("./best_score.txt", F_OK) != 0) { + return 0; + } + + FILE *fp; + char buff[10]; + fp = fopen("./best_score.txt", "r"); + fscanf(fp, "%s", buff); + int bs; + sscanf(buff, "%d", &bs); + return bs; + +} + +// save_best_score_to_file puts the best score (from global var best_score) to best_score.txt +void save_best_score_to_file(int score) { + + int best_score = score; + FILE *fp = fopen("./best_score.txt", "w"); + char snum[5]; + sprintf(snum, "%d", best_score); + fputs(snum, fp); + fclose(fp); + +} + +float points_distance(int x1, int y1, int x2, int y2) { + return sqrt(pow(x2- x1, 2) + pow(y2-y1, 2)); +} + +int is_player_inside_lemon(int player_x, int player_y, int lemon_x, int lemon_y) { + return points_distance(player_x, player_y, lemon_x+32, lemon_y+32) < 32; +} + + +void entity_decelerate(float *speed_x, float *speed_y, float deceleration) { + + if(*speed_x > 0) { + *speed_x -= deceleration; + }else{ + *speed_x += deceleration; + } + if(*speed_y > 0) { + *speed_y -= deceleration; + }else{ + *speed_y += deceleration; + } + +} +void player_decelerate(float *speed_x, float *speed_y) { + entity_decelerate(speed_x, speed_y, 0.1); +} +void lemon_decelerate(float *speed_x, float *speed_y) { + entity_decelerate(speed_x, speed_y, 0.005); + *speed_y += 0.05; +} + +void entity_cap(float *speed_x, float *speed_y) { + + if(*speed_x > 3) { + *speed_x = 3; + } + if(*speed_x < -3) { + *speed_x = -3; + } + if(*speed_y > 3) { + *speed_y = 3; + } + if(*speed_y < -3) { + *speed_y = -3; + } + +} +void player_cap(float *speed_x, float *speed_y) { + entity_cap(speed_x, speed_y); +} +void lemon_cap(float *speed_x, float *speed_y) { + entity_cap(speed_x, speed_y); +} + +void player_approximate(float *player_speed_x, float *player_speed_y) { + if(*player_speed_x > -0.1 && *player_speed_x < 0.1) { + *player_speed_x = 0; + } + if(*player_speed_y > -0.1 && *player_speed_y < 0.1) { + *player_speed_y = 0; + } +} + +void avoid_entity_outside_bonds(int *x, int *y, float *speed_x, float *speed_y, int br_x, int br_y) { + if(*x < 20 || *x > br_x) { + if(*x < 20) { + *x = 20; + }else{ + *x = br_x; + } + *speed_x = -*speed_x; + } + if(*y < 20 || *y > br_y) { + if(*y < 20) { + *y = 20; + }else{ + *y = br_y; + } + *speed_y = -*speed_y; + } +} +void avoid_player_outside_bonds(int *x, int *y, float *speed_x, float *speed_y) { + avoid_entity_outside_bonds(x, y, speed_x, speed_y, 284, 204); +} +void avoid_lemon_outside_bonds(int *x, int *y, float *speed_x, float *speed_y) { + avoid_entity_outside_bonds(x, y, speed_x, speed_y, 237, 157); +} + +int check_player_inside_prints(int tail_x, int tail_y, int paw1_x, int paw1_y, int paw2_x, int paw2_y) { + + if(tail_x + 5 >= paw1_x && tail_x <= paw1_x + 10) { + if(tail_y + 5 >= paw1_y && tail_y <= paw1_y + 10) { + return 1; + } + } + if(tail_x + 5 >= paw2_x && tail_x <= paw2_x + 10) { + if(tail_y + 5 >= paw2_y && tail_y <= paw2_y + 10) { + return 1; + } + } + + return 0; + +} \ No newline at end of file diff --git a/src/logic.h b/src/logic.h new file mode 100644 index 0000000..990119e --- /dev/null +++ b/src/logic.h @@ -0,0 +1,15 @@ +int get_best_score_from_file(void); +void save_best_score_to_file(int); + +int is_player_inside_lemon(int, int, int, int); + +void player_decelerate(float*, float*); +void player_cap(float*, float*); +void player_approximate(float*, float*); +void avoid_player_outside_bonds(int*, int*, float*, float*); + +void lemon_decelerate(float*, float*); +void lemon_cap(float*, float*); +void avoid_lemon_outside_bonds(int*, int*, float*, float*); + +int check_player_inside_prints(int, int, int, int, int, int); \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f379d57 --- /dev/null +++ b/src/main.c @@ -0,0 +1,49 @@ +#include "include.h" + +//#include "main.h" +#include "audio.h" +#include "match.h" +#include "graphics.h" + +SDL_Surface *tilesIMG; +SDL_Surface *fpsFontIMG; + +int main(void) { + + // attempt to initialize graphics and timer systema + if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) != 0) { + printf("error initializing SDL: %s\n", SDL_GetError()); + return 1; + } + + atexit(SDL_Quit); + + SDL_Surface * screen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE); + if (!screen) { + printf("error creating window: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + SDL_ShowCursor(SDL_DISABLE); + + if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) != 0) { + printf("error initializing SDL Mixer: %s\n", Mix_GetError()); + } + load_audio(); + + tilesIMG = load_asset("assets/images/JILJIL.png"); + fpsFontIMG = load_asset("assets/images/fpsfont.png"); + + int quit = 0; + quit = boot_animation(screen); + if(!quit) { + while(!quit) { + quit = match(screen); + } + } + + SDL_Quit(); + unload_audio(); + Mix_Quit(); + +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..ee1df09 --- /dev/null +++ b/src/main.h @@ -0,0 +1,7 @@ +#ifndef MAINDOTH +#define MAINDOTH + +extern SDL_Surface *tilesIMG; +extern SDL_Surface *fpsFontIMG; + +#endif \ No newline at end of file diff --git a/src/match.c b/src/match.c new file mode 100644 index 0000000..44d6a41 --- /dev/null +++ b/src/match.c @@ -0,0 +1,351 @@ +#include "include.h" + +#include "main.h" +#include "audio.h" +#include "logic.h" +#include "graphics.h" +#include "keys.h" + +int pause_game(SDL_Surface *screen) { + + pause_bgm(); + //return 1 = quit; return 0 = proceed + SDL_Surface *pauseIMG = load_asset("assets/images/pause.png"); + + SDL_BlitSurface(pauseIMG, NULL, screen, NULL); + SDL_Flip(screen); + + SDL_FreeSurface(pauseIMG); + + SDL_Event event; + while (1) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return 1; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: //select -> exit + return 1; + case SDLK_RETURN: //start -> continue + resume_bgm(); + return 0; + case SDLK_BACKSPACE: //R -> reset + resume_bgm(); + return 2; + break; + case SDLK_LSHIFT: //Y -> clear best score + save_best_score_to_file(0); + resume_bgm(); + return 2; + case SDLK_SPACE: //X -> zen mode + // to be implemented soon (TM) + break; + case SDLK_LALT: //B -> hard mode + // to be implemented soon (TM) + break; + case SDLK_LCTRL: //A -> normal + // to be implemented soon (TM) + break; + default: + break; + } + } + } + SDL_Delay(100); + } + +} + +int match(SDL_Surface *screen) { + + //return 1 = quit; return 0 = new game + + int game_over = 0; + + int player_x = 155; + int player_y = 213; + float player_speed_x = 0; + float player_speed_y = 0; + + int player_last_x_1 = 0; + int player_last_y_1 = 0; + int paw1_x = 0; + int paw1_y = 0; + int player_last_x_2 = 0; + int player_last_y_2 = 0; + int paw2_x = 0; + int paw2_y = 0; + + int lemon_x = 0; + int lemon_y = 0; + float lemon_speed_x = 2.5; + float lemon_speed_y = 2.5; + + int down_keys[6] = {0}; + int score = 0; + int best_score = get_best_score_from_file(); + + int player_past_x[40] = {0}; + int player_past_y[40] = {0}; + + long long frame = 0; + long long last_point = 0; + + play_sound("game_start"); + stop_bgm(); + play_bgm("in_game"); + while(!game_over) { + + + frame++; + Uint32 start = SDL_GetTicks(); + SDL_Event event; + + // add or remove keys to the down keys array + int key = 0; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return 1; + case SDL_KEYDOWN: + key = internal_keycode_from_sdl(event.key.keysym.sym); + if(key != -1) { + down_keys[key] = 1; + } + break; + case SDL_KEYUP: + key = internal_keycode_from_sdl(event.key.keysym.sym); + if(key != -1) { + down_keys[key] = 0; + } + break; + } + } + + player_decelerate(&player_speed_x, &player_speed_y); + player_cap(&player_speed_x, &player_speed_y); + player_approximate(&player_speed_x, &player_speed_y); + avoid_player_outside_bonds(&player_x, &player_y, &player_speed_x, &player_speed_y); + + // add speed according to down keys + if(down_keys[0]) { + player_speed_y -= 0.2; + } + if(down_keys[1]) { + player_speed_x += 0.2; + } + if(down_keys[2]) { + player_speed_y += 0.2; + } + if(down_keys[3]) { + player_speed_x -= 0.2; + } + + // add player speed to player position + player_x += player_speed_x; + player_y += player_speed_y; + + + lemon_decelerate(&lemon_speed_x, &lemon_speed_y); + lemon_cap(&lemon_speed_x, &lemon_speed_y); + avoid_lemon_outside_bonds(&lemon_x, &lemon_y, &lemon_speed_x, &lemon_speed_y); + + // add lemon speed to lemon position + lemon_x += lemon_speed_x; + lemon_y += lemon_speed_y; + + if (is_player_inside_lemon(player_x, player_y, lemon_x, lemon_y)) { + lemon_speed_x = lemon_speed_x + player_speed_x; + lemon_speed_y = lemon_speed_y + player_speed_y; + player_speed_x = -player_speed_x * 0.9; + player_speed_y = -player_speed_y * 0.9; + if(last_point + 30 < frame) { + score++; + play_sound("clap"); + last_point = frame; + } + } + + clear_screen(screen); + + // update paw prints + if(frame % 30 == 0) { + if((frame / 30) % 2 == 0) { + player_last_x_1 = player_past_x[0]; + player_last_y_1 = player_past_y[0]; + paw1_x = player_last_x_2; + paw1_y = player_last_y_2; + }else{ + player_last_x_2 = player_past_x[0]; + player_last_y_2 = player_past_y[0]; + paw2_x = player_last_x_1; + paw2_y = player_last_y_1; + } + } + + // TEST + // SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 31, y: 79, w: 5, h: 5}, screen, &(SDL_Rect){x: player_past_x[5], y: player_past_y[5]}); + + if(check_player_inside_prints(player_past_x[5], player_past_y[5], paw1_x, paw1_y, paw2_x, paw2_y)) { + if(frame > 180) { + game_over = 1; + } + } + + // draw lemon + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 0, y: 48, w: 64, h: 64}, screen, &(SDL_Rect){x: lemon_x, y: lemon_y}); + + // add position to past positions and draw tail pieces + int *temp_past_x; + temp_past_x = player_past_x; + int *temp_past_y; + temp_past_y = player_past_y; + int i; + for(i = 0; i < 39; i++) { + player_past_x[i] = temp_past_x[i+1]; + player_past_y[i] = temp_past_y[i+1]; + if(i % 5 == 0 && player_past_x[i] != 0 && player_past_y[i] != 0) { + // draw player tail pieces + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 128 - i/5 * 16, y: 0, w: 16, h: 16}, screen, &(SDL_Rect){x: player_past_x[i], y: player_past_y[i]}); + } + } + player_past_x[39] = player_x; + player_past_y[39] = player_y; + + // draw player head + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 0, y: 0, w: 16, h: 16}, screen, &(SDL_Rect){x: player_x, y: player_y}); + + // add paw prints + if(paw1_x != 0) { // make sure it isn't in the first secs of the game where random prints would appear in top left + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 0, y: 16, w: 32, h: 32}, screen, &(SDL_Rect){x: paw1_x, y: paw1_y}); + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 32, y: 16, w: 32, h: 32}, screen, &(SDL_Rect){x: paw2_x, y: paw2_y}); + } + + // handle pause input + int was_paused = 0; + if(down_keys[4] || down_keys[5]) { + switch(pause_game(screen)) { + case 1: // request to exit + return 1; + case 2: // restart the game + return 0; + } + was_paused = 1; + down_keys[4] = 0; + down_keys[5] = 0; + } + + print_score(276, 204, score, screen); // current score + print_score(276, 21, best_score, screen); // best score + + + SDL_Flip(screen); + + // sleep so that the fps stays at abt 60fps + if(!was_paused) { + + Uint32 end = SDL_GetTicks(); + float elapsedMS = end - start; + + SDL_Delay(floor(16.666f - elapsedMS)); + + } + + } + + stop_bgm(); + play_bgm("game_over"); + + if(score > best_score) { + save_best_score_to_file(score); + } + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 32, w: 64, h: 16}, screen, &(SDL_Rect){x: 133, y: 206}); // push start + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 16, w: 16, h: 16}, screen, &(SDL_Rect){x: player_x, y: player_y}); // caught face + SDL_Flip(screen); + + SDL_Event event; + while (1) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return 1; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: //select -> pause menu + pause_game(screen); + case SDLK_RETURN: //start -> new game + return 0; + default: + break; + } + } + } + SDL_Delay(100); + } + + return 0; + +} + +int boot_animation(SDL_Surface *screen) { + + //return 1 = quit 0 = continue; + + SDL_Event event; + SDL_Flip(screen); + + play_sound_and_wait("inhale"); + SDL_Rect SrcR = {x: 89, y: 64, w: 35, h: 20}; + SDL_Rect DestR = {x: 126, y: 51}; + SDL_BlitSurface(tilesIMG, &SrcR, screen, &DestR); //Jil + SDL_Flip(screen); + + DestR.x = 126+35; + SDL_BlitSurface(tilesIMG, &SrcR, screen, &DestR); //Jil + SDL_Flip(screen); + + play_sound_and_wait("sneeze_long"); + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 80, y: 25, w: 44, h: 7}, screen, &(SDL_Rect){x: 138, y: 121}); //Date + SDL_Flip(screen); + + play_sound_and_wait("sneeze_short"); + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 64, y: 103, w: 55, h: 9}, screen, &(SDL_Rect){x: 133, y: 141}); //Tortoiseshell + SDL_Flip(screen); + //SDL_Delay(1000); + + play_sound_and_wait("cough_cough"); + while (SDL_PollEvent(&event)) { + // discard the inputs + } + + SDL_BlitSurface(tilesIMG, &(SDL_Rect){x: 66, y: 37, w: 62, h: 10}, screen, &(SDL_Rect){x: 133, y: 166}); //Push start + SDL_Flip(screen); + + play_sound("ronf"); + + while (1) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return 1; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: //select -> pause menu + if(pause_game(screen)) { + return 1; + } + case SDLK_RETURN: //start -> continue + return 0; + default: + break; + } + } + } + SDL_Delay(100); + } + +} \ No newline at end of file diff --git a/src/match.h b/src/match.h new file mode 100644 index 0000000..770ee06 --- /dev/null +++ b/src/match.h @@ -0,0 +1,3 @@ +int match(SDL_Surface *); +int pause_game(SDL_Surface *); +int boot_animation(SDL_Surface *); \ No newline at end of file