Initial commit

This commit is contained in:
Massive Box 2021-07-01 14:49:46 +00:00 committed by GitHub
commit e75581fa78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 930 additions and 0 deletions

17
Makefile Normal file
View file

@ -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

20
Makefile.RS97 Normal file
View file

@ -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

36
README.md Normal file
View file

@ -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.

BIN
assets/bgm/game_over Normal file

Binary file not shown.

BIN
assets/bgm/in_game Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
assets/images/JILJIL.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
assets/images/fpsfont.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
assets/images/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

BIN
assets/images/pause.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

BIN
assets/sfx/bongo Normal file

Binary file not shown.

BIN
assets/sfx/cat_sound Normal file

Binary file not shown.

BIN
assets/sfx/cho Normal file

Binary file not shown.

BIN
assets/sfx/clap Normal file

Binary file not shown.

BIN
assets/sfx/cough_cough Normal file

Binary file not shown.

BIN
assets/sfx/game_start Normal file

Binary file not shown.

BIN
assets/sfx/inhale Normal file

Binary file not shown.

BIN
assets/sfx/reverse Normal file

Binary file not shown.

BIN
assets/sfx/ronf Normal file

Binary file not shown.

BIN
assets/sfx/rumble Normal file

Binary file not shown.

BIN
assets/sfx/sneeze_long Normal file

Binary file not shown.

BIN
assets/sfx/sneeze_short Normal file

Binary file not shown.

11
ipk/control/control Normal file
View file

@ -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

9
ipk/create-ipk.sh Normal file
View file

@ -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 ..

View file

@ -0,0 +1,4 @@
title=JilJil
description=Arcade highscore-based game.
exec=/home/retrofw/games/jiljil-c/jiljil.dge
clock=600

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

1
ipk/debian-binary Normal file
View file

@ -0,0 +1 @@
2.0

128
src/audio.c Normal file
View file

@ -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);
}

10
src/audio.h Normal file
View file

@ -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);

77
src/graphics.c Normal file
View file

@ -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
}

8
src/graphics.h Normal file
View file

@ -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[]);

11
src/include.h Normal file
View file

@ -0,0 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "SDL/SDL_mixer.h"
#include "SDL/SDL_sound.h"

37
src/keys.c Normal file
View file

@ -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;
}
}

1
src/keys.h Normal file
View file

@ -0,0 +1 @@
int internal_keycode_from_sdl(int);

135
src/logic.c Normal file
View file

@ -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;
}

15
src/logic.h Normal file
View file

@ -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);

49
src/main.c Normal file
View file

@ -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();
}

7
src/main.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef MAINDOTH
#define MAINDOTH
extern SDL_Surface *tilesIMG;
extern SDL_Surface *fpsFontIMG;
#endif

351
src/match.c Normal file
View file

@ -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);
}
}

3
src/match.h Normal file
View file

@ -0,0 +1,3 @@
int match(SDL_Surface *);
int pause_game(SDL_Surface *);
int boot_animation(SDL_Surface *);