forked from KolibriOS/kolibrios
upload dino game, add to img, to game center
This commit is contained in:
parent
2d9007da32
commit
7a6d042da7
@ -39,6 +39,7 @@ img_files = {
|
||||
{"3D/HOUSE.3DS", "common/3d/house.3ds"},
|
||||
{"File Managers/ICONS.INI", "common/File Managers/icons.ini"},
|
||||
{"GAMES/FLPYBIRD", SRC_PROGS .. "/games/flappybird/Release/flappybird"},
|
||||
{"GAMES/DINO", SRC_PROGS .. "/games/dino/dino"},
|
||||
{"FONTS/TAHOMA.KF", "common/fonts/tahoma.kf"},
|
||||
-- {"LIB/ICONV.OBJ", "common/lib/iconv.obj"},
|
||||
{"LIB/KMENU.OBJ", "common/lib/kmenu.obj"},
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB |
@ -16,6 +16,7 @@ Freecell=games/freecell,68
|
||||
Pong=games/pong,101
|
||||
Pong3=games/pong3,12
|
||||
Arcanii=/kg/arcanii,12
|
||||
Dino=games/dino,129
|
||||
|
||||
[Arcade]
|
||||
LaserTank=/kg/lasertank/lasertank,72
|
||||
|
18
programs/games/dino/Makefile
Normal file
18
programs/games/dino/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
KTCC_DIR = ../kolibrios-nextgen/programs/develop/ktcc/trunk
|
||||
KLIBC = $(KTCC_DIR)/libc.obj
|
||||
|
||||
NAME = dino
|
||||
|
||||
KTCC = $(KTCC_DIR)/bin/kos32-tcc
|
||||
KPACK = kpack
|
||||
|
||||
SRC = $(wildcard *.c)
|
||||
FLAGS= -B$(KTCC_DIR)/bin -I $(KLIBC)/include -Wall -stack=20480
|
||||
LIBS = -limg
|
||||
|
||||
all: $(SRC)
|
||||
$(KTCC) $(FLAGS) $(SRC) $(LIBS) -o $(NAME)
|
||||
# $(KPACK) $(NAME)
|
||||
|
||||
clean:
|
||||
rm $(NAME)
|
25
programs/games/dino/Tupfile.lua
Normal file
25
programs/games/dino/Tupfile.lua
Normal file
@ -0,0 +1,25 @@
|
||||
if tup.getconfig("NO_TCC") ~= "" then return end
|
||||
if tup.getconfig("HELPERDIR") == ""
|
||||
then
|
||||
HELPERDIR = "../../../programs"
|
||||
end
|
||||
tup.include(HELPERDIR .. "/use_tcc.lua")
|
||||
|
||||
SRCS = {
|
||||
"cloud.c"
|
||||
"game_over_panel.c"
|
||||
"horizon.c"
|
||||
"main.c"
|
||||
"obstacle.c"
|
||||
"trex.c
|
||||
"distance_meter.c"
|
||||
"graphics.c"
|
||||
"horizon_line.c"
|
||||
"misc.c"
|
||||
"runner.c"
|
||||
"ulist.c
|
||||
}
|
||||
|
||||
LIBS = " -limg"
|
||||
|
||||
link_tcc(SRCS, "dino");
|
34
programs/games/dino/cloud.c
Normal file
34
programs/games/dino/cloud.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include "cloud.h"
|
||||
|
||||
void cloudInit(Cloud* cloud, int w) {
|
||||
cloud->width = w;
|
||||
cloud->xPos = w;
|
||||
cloud->yPos = 0;
|
||||
cloud->remove = false;
|
||||
cloud->cloudGap = getRandomNumber(CLOUD_MIN_GAP, CLOUD_MAX_GAP);
|
||||
|
||||
cloud->yPos = getRandomNumber(CLOUD_MAX_SKY_LEVEL, CLOUD_MIN_SKY_LEVEL); // NOTE why swapped
|
||||
cloudDraw(cloud);
|
||||
}
|
||||
|
||||
void cloudDraw(const Cloud* cloud) {
|
||||
graphicsBlitAtlasImage(ATLAS_CLOUD_X, ATLAS_CLOUD_Y, cloud->xPos, cloud->yPos, CLOUD_WIDTH, CLOUD_HEIGHT, false);
|
||||
}
|
||||
|
||||
void cloudUpdate(Cloud* cloud, double speed) {
|
||||
// printf("cloudUpdate(., %f)\n", speed);
|
||||
if (!cloud->remove) {
|
||||
cloud->xPos -= (int)ceil(speed);
|
||||
cloudDraw(cloud);
|
||||
|
||||
// Mark as removeable if no longer in the canvas.
|
||||
if (!cloudIsVisible(cloud)) {
|
||||
cloud->remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cloudIsVisible(const Cloud* cloud) {
|
||||
return cloud->xPos + CLOUD_WIDTH > 0;
|
||||
}
|
||||
|
29
programs/games/dino/cloud.h
Normal file
29
programs/games/dino/cloud.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef CLOUD_H
|
||||
#define CLOUD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define CLOUD_WIDTH 46
|
||||
#define CLOUD_HEIGHT 14
|
||||
#define CLOUD_MAX_GAP 400
|
||||
#define CLOUD_MAX_SKY_LEVEL 30
|
||||
#define CLOUD_MIN_GAP 100
|
||||
#define CLOUD_MIN_SKY_LEVEL 71
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int xPos;
|
||||
int yPos;
|
||||
bool remove;
|
||||
int cloudGap;
|
||||
} Cloud;
|
||||
|
||||
void cloudInit(Cloud* cloud, int w);
|
||||
void cloudDraw(const Cloud* cloud);
|
||||
void cloudUpdate(Cloud* cloud, double speed);
|
||||
bool cloudIsVisible(const Cloud* cloud);
|
||||
|
||||
#endif
|
11
programs/games/dino/collisionbox.h
Normal file
11
programs/games/dino/collisionbox.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef COLLISIONBOX_H
|
||||
#define COLLISIONBOX_H
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} CollisionBox;
|
||||
|
||||
#endif
|
19
programs/games/dino/config.h
Normal file
19
programs/games/dino/config.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define DEFAULT_WIDTH 600
|
||||
#define FPS 60
|
||||
|
||||
#define DELTA_MS_DEFAULT 20
|
||||
|
||||
#define WINDOW_TITLE "DINO. Jump: UP/SPACE Duck: DOWN Restart: jump or ENTER"
|
||||
|
||||
// #define DBG
|
||||
|
||||
#ifdef DBG
|
||||
#define dbg_printf(...) debug_printf(__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_printf(...)
|
||||
#endif
|
||||
|
||||
#endif
|
134
programs/games/dino/distance_meter.c
Normal file
134
programs/games/dino/distance_meter.c
Normal file
@ -0,0 +1,134 @@
|
||||
#include "distance_meter.h"
|
||||
|
||||
DistanceMeter distanceMeter;
|
||||
|
||||
void distanceMeterInit(int w) {
|
||||
distanceMeter.x = 0;
|
||||
distanceMeter.y = 5;
|
||||
distanceMeter.currentDistance = 0;
|
||||
distanceMeter.maxScore = 0;
|
||||
distanceMeter.achievement = false;
|
||||
distanceMeter.flashTimer = 0;
|
||||
distanceMeter.flashIterations = 0;
|
||||
distanceMeter.invertTrigger = false;
|
||||
distanceMeter.maxScoreUnits = DM_MAX_DISTANCE_UNITS;
|
||||
distanceMeterCalcXPos(w);
|
||||
for (int i = 0; i < distanceMeter.maxScoreUnits; i++) {
|
||||
distanceMeterDraw(i, 0, false);
|
||||
}
|
||||
distanceMeter.maxScore = (int)pow(10, distanceMeter.maxScoreUnits) - 1;
|
||||
distanceMeter.digits[0] = '\0';
|
||||
distanceMeter.highScore[0] = '\0';
|
||||
}
|
||||
|
||||
void distanceMeterCalcXPos(int w) {
|
||||
distanceMeter.x = w - (DM_DEST_WIDTH * (distanceMeter.maxScoreUnits + 1));
|
||||
}
|
||||
|
||||
void distanceMeterDraw(int digitPos, int value, bool opt_highscore) {
|
||||
|
||||
int dx, dy;
|
||||
if (opt_highscore) {
|
||||
dx = distanceMeter.x - (distanceMeter.maxScoreUnits * 2) * DM_WIDTH;
|
||||
dy = distanceMeter.y;
|
||||
}
|
||||
else {
|
||||
dx = distanceMeter.x;
|
||||
dy = distanceMeter.y;
|
||||
}
|
||||
//printf("%d %d %d %d %d %d\n", digitPos, value, opt_highscore, dx, dy, DM_WIDTH * value + ATLAS_TEXT_SPRITE_X);
|
||||
graphicsBlitAtlasImage(
|
||||
DM_WIDTH * value + ATLAS_TEXT_SPRITE_X,
|
||||
0 + ATLAS_TEXT_SPRITE_Y,
|
||||
digitPos * DM_DEST_WIDTH + dx,
|
||||
distanceMeter.y + dy,
|
||||
DM_WIDTH,
|
||||
DM_HEIGHT,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
void distanceMeterDrawHighScore() {
|
||||
// TODO canvasCtx.globalAlpha = .8;
|
||||
for (int i = (int)strlen(distanceMeter.highScore) - 1; i >= 0; i--) {
|
||||
distanceMeterDraw(i, distanceMeter.highScore[i] > 12 ? distanceMeter.highScore[i] - '0' : distanceMeter.highScore[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
void distanceMeterSetHighScore(int _distance) {
|
||||
int distance = distanceMeterGetActualDistance(_distance);
|
||||
distanceMeter.highScore[0] = 10;
|
||||
distanceMeter.highScore[1] = 11;
|
||||
distanceMeter.highScore[2] = 12;
|
||||
intToStr(distance, distanceMeter.maxScoreUnits, distanceMeter.highScore + 3);
|
||||
}
|
||||
|
||||
void distanceMeterReset() {
|
||||
distanceMeterUpdate(0, 0);
|
||||
distanceMeter.achievement = false;
|
||||
}
|
||||
|
||||
int distanceMeterGetActualDistance(int distance) {
|
||||
return distance ? (int)round(distance * DM_COEFFICIENT) : 0;
|
||||
}
|
||||
|
||||
bool distanceMeterUpdate(int deltaTime, int _distance) {
|
||||
bool paint = true;
|
||||
bool playSound = false;
|
||||
int distance = _distance;
|
||||
if (!distanceMeter.achievement) {
|
||||
distance = distanceMeterGetActualDistance(distance);
|
||||
// check if score has gone beyond the initial digit count.
|
||||
if (distance > distanceMeter.maxScore && distanceMeter.maxScoreUnits == DM_MAX_DISTANCE_UNITS) {
|
||||
distanceMeter.maxScoreUnits++;
|
||||
distanceMeter.maxScore = distanceMeter.maxScore * 10 + 9;
|
||||
}
|
||||
// else {
|
||||
// NOTE this.distance was in original but i didsnt see any usage of this field
|
||||
// }
|
||||
|
||||
if (distance > 0) {
|
||||
// Acheivement unlocked
|
||||
if (distance % DM_ACHIEVEMENT_DISTANCE == 0) {
|
||||
// Flash score and play sound
|
||||
distanceMeter.achievement = true;
|
||||
distanceMeter.flashTimer = 0;
|
||||
playSound = true;
|
||||
}
|
||||
// Create a string representation of the distance with leading 0.
|
||||
intToStr(distance, distanceMeter.maxScoreUnits, distanceMeter.digits);
|
||||
}
|
||||
else {
|
||||
intToStr(0, distanceMeter.maxScoreUnits, distanceMeter.digits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Control flashing of the score on reaching acheivement.
|
||||
if (distanceMeter.flashIterations <= DM_FLASH_ITERATIONS) {
|
||||
distanceMeter.flashTimer += deltaTime;
|
||||
|
||||
if (distanceMeter.flashTimer < DM_FLASH_DURATION) {
|
||||
paint = false;
|
||||
}
|
||||
else if (distanceMeter.flashTimer > DM_FLASH_DURATION * 2) {
|
||||
distanceMeter.flashTimer = 0;
|
||||
distanceMeter.flashIterations++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
distanceMeter.achievement = false;
|
||||
distanceMeter.flashIterations = 0;
|
||||
distanceMeter.flashTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the digits if not flashing
|
||||
if (paint) {
|
||||
for (int i = distanceMeter.maxScoreUnits - 1; i >= 0; i--) {
|
||||
distanceMeterDraw(i, (int)distanceMeter.digits[i] - '0', false);
|
||||
}
|
||||
}
|
||||
|
||||
distanceMeterDrawHighScore();
|
||||
return playSound;
|
||||
}
|
44
programs/games/dino/distance_meter.h
Normal file
44
programs/games/dino/distance_meter.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef DISTANCE_METER_H
|
||||
#define DISTANCE_METER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define DM_MAX_DISTANCE_UNITS 5
|
||||
#define DM_ACHIEVEMENT_DISTANCE 100
|
||||
#define DM_COEFFICIENT 0.025
|
||||
#define DM_FLASH_DURATION 1000/4
|
||||
#define DM_FLASH_ITERATIONS 3
|
||||
#define DM_WIDTH 10
|
||||
#define DM_HEIGHT 13
|
||||
#define DM_DEST_WIDTH 11
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int currentDistance;
|
||||
int maxScore;
|
||||
char digits[16];
|
||||
char highScore[16];
|
||||
bool achievement;
|
||||
int flashTimer;
|
||||
int flashIterations;
|
||||
bool invertTrigger;
|
||||
int maxScoreUnits;
|
||||
} DistanceMeter;
|
||||
|
||||
extern DistanceMeter distanceMeter;
|
||||
|
||||
void distanceMeterInit(int w);
|
||||
void distanceMeterCalcXPos(int w);
|
||||
void distanceMeterDraw(int digitPos, int value, bool opt_highscore);
|
||||
int distanceMeterGetActualDistance(int distance);
|
||||
bool distanceMeterUpdate(int deltaTime, int _distance);
|
||||
void distanceMeterDrawHighScore();
|
||||
void distanceMeterSetHighScore(int _distance);
|
||||
void distanceMeterReset();
|
||||
|
||||
#endif
|
22
programs/games/dino/game_over_panel.c
Normal file
22
programs/games/dino/game_over_panel.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "game_over_panel.h"
|
||||
|
||||
GameOverPanel gameOverPanel;
|
||||
|
||||
void gameOverPanelInit(int width, int height) {
|
||||
gameOverPanel.width = width;
|
||||
gameOverPanel.height = height;
|
||||
}
|
||||
|
||||
void gameOverPanelDraw() {
|
||||
double centerX = gameOverPanel.width / 2;
|
||||
int textTargetX = (int)round(centerX - (GOP_TEXT_WIDTH / 2));
|
||||
int textTargetY = (int)round((gameOverPanel.height - 25) / 3);
|
||||
int restartTargetX = centerX - (GOP_RESTART_WIDTH / 2);
|
||||
int restartTargetY = gameOverPanel.height / 2;
|
||||
// Game over text from sprite
|
||||
graphicsBlitAtlasImage(GOP_TEXT_X + ATLAS_TEXT_SPRITE_X, GOP_TEXT_Y + ATLAS_TEXT_SPRITE_Y,
|
||||
textTargetX, textTargetY, GOP_TEXT_WIDTH, GOP_TEXT_HEIGHT, false);
|
||||
// Restart button
|
||||
graphicsBlitAtlasImage(ATLAS_RESTART_X, ATLAS_RESTART_Y,
|
||||
restartTargetX, restartTargetY, GOP_RESTART_WIDTH, GOP_RESTART_HEIGHT, false);
|
||||
}
|
24
programs/games/dino/game_over_panel.h
Normal file
24
programs/games/dino/game_over_panel.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef GAME_OVER_PANEL_H
|
||||
#define GAME_OVER_PANEL_H
|
||||
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
|
||||
#define GOP_TEXT_X 0
|
||||
#define GOP_TEXT_Y 13
|
||||
#define GOP_TEXT_WIDTH 191
|
||||
#define GOP_TEXT_HEIGHT 11
|
||||
#define GOP_RESTART_WIDTH 36
|
||||
#define GOP_RESTART_HEIGHT 32
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
} GameOverPanel;
|
||||
|
||||
extern GameOverPanel gameOverPanel;
|
||||
|
||||
void gameOverPanelInit(int width, int height);
|
||||
void gameOverPanelDraw();
|
||||
|
||||
#endif
|
115
programs/games/dino/graphics.c
Normal file
115
programs/games/dino/graphics.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "graphics.h"
|
||||
#include "sprites.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*static*/ ksys_colors_table_t sys_color_table;
|
||||
/*static*/ ksys_pos_t win_pos;
|
||||
/*static*/ Image* screenImage;
|
||||
/*static*/ Image* spriteAtlas;
|
||||
|
||||
|
||||
void graphicsInit() {
|
||||
win_pos = _ksys_get_mouse_pos(KSYS_MOUSE_SCREEN_POS);
|
||||
_ksys_get_system_colors(&sys_color_table);
|
||||
spriteAtlas = img_decode((void*)sprites100, sizeof(sprites100), 0);
|
||||
*((uint8_t*)spriteAtlas->Palette + 3) = 0; // set black as transparent
|
||||
// for (int i = 0; i < 16; i++) {
|
||||
// dbg_printf("%x\n", *((uint8_t*)spriteAtlas->Palette + i));
|
||||
// }
|
||||
if (spriteAtlas->Type != IMAGE_BPP32) {
|
||||
spriteAtlas = img_convert(spriteAtlas, NULL, IMAGE_BPP32, 0, 0);
|
||||
if (!spriteAtlas) {
|
||||
dbg_printf("spriteAtlas convert error\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
dbg_printf("spriteAtlas->Type = %d\n", spriteAtlas->Type);
|
||||
screenImage = img_create(DEFAULT_WIDTH, 200, IMAGE_BPP32);
|
||||
// asm_inline("emms"); // doenst need bec. libimg functions used here does not use mmx (=> does not currept fpu state)
|
||||
}
|
||||
|
||||
// void save_fpu_state(void *fpustate) {
|
||||
// __asm__("fsave %0" : "=m" (*fpustate) : : "memory");
|
||||
// }
|
||||
|
||||
// void restore_fpu_state(const void *fpustate) {
|
||||
// __asm__("fnsave %0" : : "m" (*fpustate));
|
||||
// }
|
||||
|
||||
|
||||
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center) {
|
||||
// dbg_printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
|
||||
|
||||
// asm_inline("int $3");
|
||||
|
||||
int screen_width = (int)screenImage->Width;
|
||||
int screen_height = (int)screenImage->Height;
|
||||
|
||||
if (destX >= screen_width) {
|
||||
return;
|
||||
}
|
||||
if (destY >= screen_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (destX < 0) {
|
||||
atlasX -= destX;
|
||||
w = destX + w;
|
||||
destX = 0;
|
||||
}
|
||||
if (destX + w > screen_width) {
|
||||
w = screen_width - destX;
|
||||
}
|
||||
|
||||
if (destY < 0) {
|
||||
atlasY -= destY;
|
||||
h = destY + h;
|
||||
destY = 0;
|
||||
}
|
||||
if (destY + h > screen_height) {
|
||||
h = screen_height - destY;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
|
||||
|
||||
// asm_inline("int $3");
|
||||
/*unsigned char buf[512];
|
||||
save_fpu_state(buf);
|
||||
img_blend(screenImage, spriteAtlas, destX, destY, atlasX, atlasY, w, h);
|
||||
restore_fpu_state(buf);*/
|
||||
|
||||
img_blend(screenImage, spriteAtlas, destX, destY, atlasX, atlasY, w, h);
|
||||
asm_inline("emms");
|
||||
|
||||
// dbg_printf("end graphicsBlitAtlasImage\n\n");
|
||||
}
|
||||
|
||||
void graphicsFillBackground(unsigned r, unsigned g, unsigned b) {
|
||||
img_fill_color(screenImage, screenImage->Width, screenImage->Height, (0xFF << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
|
||||
void graphicsRender() {
|
||||
// don't redraw window on each frame. redraw window only when redraw event (called when widow moved e.g.)
|
||||
//_ksys_start_draw();
|
||||
//_ksys_create_window(win_pos.x, win_pos.y, screenImage->Width + 10, screenImage->Height + 29, WINDOW_TITLE, sys_color_table.work_area, 0x54); // 0x54. note: C = 1 !!
|
||||
img_draw(screenImage, 5, 24, screenImage->Width, screenImage->Height, 0, 0);
|
||||
//ksys_draw_bitmap_palette(screenImage->Data, 5, 24, screenImage->Width, screenImage->Height, 32, 0, 0);
|
||||
// ksys_blitter_params_t bp = {5, 24, screenImage->Width, screenImage->Height, 0, 0, screenImage->Width, screenImage->Height, screenImage->Data, screenImage->Width*4};
|
||||
// _ksys_blitter(0, &bp);
|
||||
//_ksys_end_draw();
|
||||
}
|
||||
|
||||
void graphicsDelay(int ms) {
|
||||
// dbg_printf("ms = %d\n", ms);
|
||||
_ksys_delay(ms/10 ? ms/10 : 2);
|
||||
}
|
||||
|
||||
|
||||
void graphicsDestroy() {
|
||||
img_destroy(screenImage);
|
||||
img_destroy(spriteAtlas);
|
||||
}
|
41
programs/games/dino/graphics.h
Normal file
41
programs/games/dino/graphics.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef GRAPHICS_H
|
||||
#define GRAPHICS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/ksys.h>
|
||||
#include <clayer/libimg.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define ATLAS_CACTUS_LARGE_X 332
|
||||
#define ATLAS_CACTUS_LARGE_Y 2
|
||||
#define ATLAS_CACTUS_SMALL_X 228
|
||||
#define ATLAS_CACTUS_SMALL_Y 2
|
||||
#define ATLAS_CLOUD_X 86
|
||||
#define ATLAS_CLOUD_Y 2
|
||||
#define ATLAS_HORIZON_X 2
|
||||
#define ATLAS_HORIZON_Y 54
|
||||
#define ATLAS_MOON_X 484
|
||||
#define ATLAS_MOON_Y 2
|
||||
#define ATLAS_PTERODACTYL_X 134
|
||||
#define ATLAS_PTERODACTYL_Y 2
|
||||
#define ATLAS_RESTART_X 2
|
||||
#define ATLAS_RESTART_Y 2
|
||||
#define ATLAS_TEXT_SPRITE_X 655
|
||||
#define ATLAS_TEXT_SPRITE_Y 2
|
||||
#define ATLAS_TREX_X 848
|
||||
#define ATLAS_TREX_Y 2
|
||||
#define ATLAS_STAR_X 645
|
||||
#define ATLAS_STAR_Y 2
|
||||
|
||||
void graphicsInit();
|
||||
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center);
|
||||
void graphicsFillBackground(unsigned r, unsigned g, unsigned b);
|
||||
void graphicsRender();
|
||||
void graphicsDelay(int ms);
|
||||
void graphicsDestroy();
|
||||
|
||||
#endif
|
147
programs/games/dino/horizon.c
Normal file
147
programs/games/dino/horizon.c
Normal file
@ -0,0 +1,147 @@
|
||||
#include "horizon.h"
|
||||
|
||||
Horizon horizon;
|
||||
|
||||
void horizonInit(int dim_width, double gapCoefficient) {
|
||||
horizon.dim_width = dim_width;
|
||||
horizon.gapCoefficient = gapCoefficient;
|
||||
horizon.obstacles = ulist_create();
|
||||
horizon.obstacleHistory = ulist_create();
|
||||
horizon.clouds = ulist_create();
|
||||
|
||||
horizonAddCloud();
|
||||
|
||||
horizonLineInit();
|
||||
}
|
||||
|
||||
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode) {
|
||||
//horizon.runningTime += deltaTime;
|
||||
horizonLineUpdate(deltaTime, currentSpeed);
|
||||
// if (currentSpeed != currentSpeed) {
|
||||
// currentSpeed = 6.0;
|
||||
// }
|
||||
// horizon.nightMode.update(showNightMode);
|
||||
horizonUpdateClouds(deltaTime, currentSpeed);
|
||||
if (updateObstacles) {
|
||||
horizonUpdateObstacles(deltaTime, currentSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void horizonUpdateClouds(int deltaTime, double speed) {
|
||||
//printf("horizonUpdateClouds()\n");
|
||||
double cloudSpeed = HORIZON_BG_CLOUD_SPEED / 1000 * deltaTime * speed;
|
||||
int numClouds = ulist_size(horizon.clouds);
|
||||
//printf("horizonUpdateClouds() %d\n", numClouds);
|
||||
|
||||
if (numClouds) {
|
||||
Node *cloudNode = horizon.clouds->tail;
|
||||
while (cloudNode != NULL) {
|
||||
cloudUpdate(cloudNode->data, cloudSpeed);
|
||||
cloudNode = cloudNode->prev;
|
||||
}
|
||||
Cloud *lastCloud = horizon.clouds->tail->data;
|
||||
// Check for adding a new cloud
|
||||
if (numClouds < HORIZON_MAX_CLOUDS && (horizon.dim_width - lastCloud->xPos) > lastCloud->cloudGap && HORIZON_CLOUD_FREQUENCY > (double)rand()/RAND_MAX) {
|
||||
horizonAddCloud();
|
||||
}
|
||||
// Remove expired clouds
|
||||
cloudNode = horizon.clouds->head;
|
||||
while (cloudNode != NULL) {
|
||||
Node* cloudNodeNext = cloudNode->next;
|
||||
Cloud* c = cloudNode->data;
|
||||
if (c->remove) {
|
||||
ulist_remove(horizon.clouds, cloudNode);
|
||||
}
|
||||
cloudNode = cloudNodeNext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
horizonAddCloud();
|
||||
}
|
||||
}
|
||||
|
||||
void horizonUpdateObstacles(int deltaTime, double currentSpeed) {
|
||||
//printf("horizonUpdateObstacles()\n");
|
||||
// Obstacles, move to Horizon layer
|
||||
Node* obNode = horizon.obstacles->head;
|
||||
while (obNode != NULL) {
|
||||
Node* obNodeNext = obNode->next;
|
||||
Obstacle* ob = obNode->data;
|
||||
obstacleUpdate(ob, deltaTime, currentSpeed);
|
||||
// Clean up existing obstacles
|
||||
if (ob->remove) {
|
||||
//ulist_remove(horizon.obstacles, obNode);
|
||||
//ulist_print(horizon.obstacles);
|
||||
ulist_remove_front(horizon.obstacles);
|
||||
//ulist_print(horizon.obstacles);
|
||||
//puts("");
|
||||
}
|
||||
obNode = obNodeNext;
|
||||
}
|
||||
|
||||
if (ulist_size(horizon.obstacles) > 0) {
|
||||
Obstacle *lastObstacle = horizon.obstacles->tail->data;
|
||||
|
||||
if (lastObstacle && !lastObstacle->followingObstacleCreated && obstacleIsVisible(lastObstacle) && (lastObstacle->xPos + lastObstacle->width + lastObstacle->gap) < horizon.dim_width) {
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
lastObstacle->followingObstacleCreated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create new obstacles.
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void horizonAddNewObstacle(double currentSpeed) {
|
||||
int obstacleTypeIndex = getRandomNumber(0, sizeof(obstacleTypeConfigs)/sizeof(ObstacleTypeConfig) - 1);
|
||||
ObstacleTypeConfig *otc = &obstacleTypeConfigs[obstacleTypeIndex];
|
||||
|
||||
// Check for multiples of the same type of obstacle.
|
||||
// Also check obstacle is available at current speed.
|
||||
if (horizonDuplicateObstacleCheck(otc->type) || currentSpeed < otc->minSpeed) {
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
}
|
||||
else {
|
||||
Obstacle* ob = malloc(sizeof(Obstacle));
|
||||
obstacleInit(ob, otc, horizon.dim_width, horizon.gapCoefficient, currentSpeed, otc->width);
|
||||
ulist_push_back(horizon.obstacles, ob);
|
||||
ulist_push_front(horizon.obstacleHistory, &(otc->type));
|
||||
if (ulist_size(horizon.obstacleHistory) > 1) {
|
||||
ulist_splice(horizon.obstacleHistory, RUNNER_MAX_OBSTACLE_DUPLICATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType) {
|
||||
//printf("horizonDuplicateObstacleCheck(%d)\n", nextObstacleType);
|
||||
int duplicateCount = 0;
|
||||
Node* ohNode = horizon.obstacleHistory->head;
|
||||
while (ohNode != NULL) {
|
||||
//printf("%d\n", *(int*)ohNode->data);
|
||||
duplicateCount = *(int*)ohNode->data == nextObstacleType ? duplicateCount + 1 : 0;
|
||||
ohNode = ohNode->next;
|
||||
}
|
||||
//printf("duplicateCount = %d\n\n", duplicateCount);
|
||||
return duplicateCount >= RUNNER_MAX_OBSTACLE_DUPLICATION;
|
||||
}
|
||||
|
||||
void horizonReset() {
|
||||
// printf("horizonReset() !!\n");
|
||||
ulist_destroy(horizon.obstacles);
|
||||
horizon.obstacles = ulist_create();
|
||||
horizonLineReset();
|
||||
}
|
||||
|
||||
//void horizonResize(int width, int height) {
|
||||
//
|
||||
//}
|
||||
|
||||
void horizonAddCloud() {
|
||||
Cloud* c = malloc(sizeof(Cloud));
|
||||
cloudInit(c, horizon.dim_width);
|
||||
//printf("horizonAddCloud() %d -> ", ulist_size(horizon.obstacles));
|
||||
ulist_push_back(horizon.clouds, c);
|
||||
//printf("%d\n", ulist_size(horizon.obstacles));
|
||||
}
|
||||
|
41
programs/games/dino/horizon.h
Normal file
41
programs/games/dino/horizon.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef HORIZON_H
|
||||
#define HORIZON_H
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "obstacle.h"
|
||||
#include "cloud.h"
|
||||
#include "horizon_line.h"
|
||||
#include "runner.h"
|
||||
#include "graphics.h"
|
||||
#include "ulist.h"
|
||||
|
||||
#define HORIZON_BG_CLOUD_SPEED 0.2
|
||||
#define HORIZON_BUMPY_THRESHOLD 0.3
|
||||
#define HORIZON_CLOUD_FREQUENCY 0.5
|
||||
#define HORIZON_HORIZON_HEIGHT 16
|
||||
#define HORIZON_MAX_CLOUDS 6
|
||||
|
||||
typedef struct {
|
||||
int dim_width;
|
||||
double gapCoefficient;
|
||||
Ulist* obstacles;
|
||||
Ulist* obstacleHistory;
|
||||
// nightMode
|
||||
Ulist* clouds;
|
||||
} Horizon;
|
||||
|
||||
extern Horizon horizon;
|
||||
|
||||
void horizonInit(int dim_width, double gapCoefficient);
|
||||
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode);
|
||||
void horizonUpdateClouds(int deltaTime, double speed);
|
||||
void horizonUpdateObstacles(int deltaTime, double currentSpeed);
|
||||
//void horizonRemoveFirstObstacle();
|
||||
void horizonAddNewObstacle(double currentSpeed);
|
||||
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType);
|
||||
void horizonReset();
|
||||
//void horizonResize(int width, int height);
|
||||
void horizonAddCloud();
|
||||
|
||||
#endif
|
56
programs/games/dino/horizon_line.c
Normal file
56
programs/games/dino/horizon_line.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "horizon_line.h"
|
||||
|
||||
HorizonLine horizonLine;
|
||||
|
||||
void horizonLineInit() {
|
||||
horizonLine.width = HORIZON_LINE_WIDTH;
|
||||
horizonLine.height = HORIZON_LINE_HEIGHT;
|
||||
horizonLine.sourceXPos[0] = ATLAS_HORIZON_X;
|
||||
horizonLine.sourceXPos[1] = ATLAS_HORIZON_X + horizonLine.width;
|
||||
horizonLine.bumpThreshold = 0.5;
|
||||
horizonLine.xPos[0] = 0;
|
||||
horizonLine.xPos[1] = horizonLine.width;
|
||||
horizonLine.yPos = HORIZON_LINE_YPOS;
|
||||
horizonLineDraw();
|
||||
}
|
||||
|
||||
void horizonLineDraw() {
|
||||
//printf("horizonLineDraw(); xPos[0] = %d, xPos[1] = %d, yPos = %d, width = %d, height = %d\n", horizonLine.xPos[0], horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height);
|
||||
graphicsBlitAtlasImage(horizonLine.sourceXPos[0], ATLAS_HORIZON_Y, horizonLine.xPos[0], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
|
||||
graphicsBlitAtlasImage(horizonLine.sourceXPos[1], ATLAS_HORIZON_Y, horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
|
||||
}
|
||||
|
||||
int horizonLineGetRandomType() {
|
||||
return (double)rand() / RAND_MAX > horizonLine.bumpThreshold ? horizonLine.width : 0;
|
||||
}
|
||||
|
||||
void horizonLineUpdateXPos(int pos, int increment) {
|
||||
int line1 = pos;
|
||||
int line2 = pos == 0 ? 1 : 0;
|
||||
|
||||
horizonLine.xPos[line1] -= increment;
|
||||
horizonLine.xPos[line2] = horizonLine.xPos[line1] + horizonLine.width;
|
||||
|
||||
if (horizonLine.xPos[line1] <= -horizonLine.width) {
|
||||
horizonLine.xPos[line1] += horizonLine.width * 2;
|
||||
horizonLine.xPos[line2] = horizonLine.xPos[line1] - horizonLine.width;
|
||||
horizonLine.sourceXPos[line1] = horizonLineGetRandomType() + ATLAS_HORIZON_X;
|
||||
}
|
||||
}
|
||||
|
||||
void horizonLineUpdate(int deltaTime, double speed) {
|
||||
int increment = floor(speed * (FPS / 1000.0) * deltaTime);
|
||||
if (horizonLine.xPos[0] <= 0) {
|
||||
horizonLineUpdateXPos(0, increment);
|
||||
}
|
||||
else {
|
||||
horizonLineUpdateXPos(1, increment);
|
||||
}
|
||||
// asm_inline("int $3");
|
||||
horizonLineDraw();
|
||||
}
|
||||
|
||||
void horizonLineReset() {
|
||||
horizonLine.xPos[0] = 0;
|
||||
horizonLine.xPos[1] = horizonLine.width;
|
||||
}
|
33
programs/games/dino/horizon_line.h
Normal file
33
programs/games/dino/horizon_line.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef HORIZON_LINE_H
|
||||
#define HORIZON_LINE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include "config.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#define HORIZON_LINE_WIDTH 600
|
||||
#define HORIZON_LINE_HEIGHT 12
|
||||
#define HORIZON_LINE_YPOS 127
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int sourceXPos[2];
|
||||
int xPos[2];
|
||||
int yPos;
|
||||
double bumpThreshold;
|
||||
} HorizonLine;
|
||||
|
||||
extern HorizonLine horizonLine;
|
||||
|
||||
void horizonLineInit();
|
||||
void horizonLineDraw();
|
||||
int horizonLineGetRandomType();
|
||||
void horizonLineUpdateXPos(int pos, int increment);
|
||||
void horizonLineUpdate(int deltaTime, double speed);
|
||||
void horizonLineReset();
|
||||
|
||||
#endif
|
133
programs/games/dino/main.c
Normal file
133
programs/games/dino/main.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/ksys.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "graphics.h"
|
||||
#include "distance_meter.h"
|
||||
#include "cloud.h"
|
||||
#include "obstacle.h"
|
||||
#include "horizon_line.h"
|
||||
#include "trex.h"
|
||||
#include "runner.h"
|
||||
|
||||
uint8_t keyboard_layout[128];
|
||||
|
||||
extern ksys_colors_table_t sys_color_table;
|
||||
extern ksys_pos_t win_pos;
|
||||
extern Image* screenImage;
|
||||
extern Image* spriteAtlas;
|
||||
|
||||
int main(int argc, char* args[]) {
|
||||
srand((unsigned int)time(NULL)); // Seed the random number generator
|
||||
|
||||
graphicsInit();
|
||||
|
||||
runnerInit();
|
||||
|
||||
dbg_printf("dino started\n");
|
||||
|
||||
_ksys_set_event_mask(0xC0000027); // !
|
||||
_ksys_set_key_input_mode(KSYS_KEY_INPUT_MODE_SCANC);
|
||||
_ksys_keyboard_layout(KSYS_KEYBOARD_LAYOUT_NORMAL, keyboard_layout);
|
||||
|
||||
int ext_code = 0;
|
||||
uint8_t old_mode = 0;
|
||||
|
||||
bool quit = false;
|
||||
while (quit == false) {
|
||||
int frameStartTime = getTimeStamp();
|
||||
//printf("frameStartTime = %d\n", frameStartTime);
|
||||
uint32_t kos_event = _ksys_check_event();
|
||||
switch (kos_event) {
|
||||
case KSYS_EVENT_BUTTON:
|
||||
switch (_ksys_get_button()){
|
||||
case 1:
|
||||
quit = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KSYS_EVENT_KEY:
|
||||
{
|
||||
ksys_oskey_t key = _ksys_get_key();
|
||||
uint8_t scancode = key.code;
|
||||
if (scancode == 0xE0 || scancode == 0xE1) {
|
||||
ext_code = scancode;
|
||||
break;
|
||||
}
|
||||
if (ext_code == 0xE1 && (scancode & 0x7F) == 0x1D) {
|
||||
break;
|
||||
}
|
||||
if (ext_code == 0xE1 && scancode == 0xC5) {
|
||||
ext_code = 0;
|
||||
break;
|
||||
}
|
||||
uint8_t code = keyboard_layout[scancode & 0x7F];
|
||||
|
||||
if (ext_code == 0xE0) {
|
||||
code -= 96;
|
||||
}
|
||||
ext_code = 0;
|
||||
|
||||
if (scancode < 128) { // KEYDOWN
|
||||
//dbg_printf("Keydown: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
|
||||
//dbg_printf("keydown c = %u\n", key.code);
|
||||
runnerOnKeyDown(code);
|
||||
} else { // KEYUP
|
||||
//dbg_printf("Keyup: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
|
||||
//dbg_printf("keyup c = %u\n", key.code);
|
||||
runnerOnKeyUp(code);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KSYS_EVENT_REDRAW:
|
||||
//dbg_printf("KSYS_EVENT_REDRAW\n");
|
||||
_ksys_start_draw();
|
||||
_ksys_create_window(win_pos.x, win_pos.y, screenImage->Width + 10, screenImage->Height + 29, WINDOW_TITLE, sys_color_table.work_area, 0x54); // 0x54. note: C = 1 !!
|
||||
graphicsRender();
|
||||
_ksys_end_draw();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (runner.nextUpdateScheduled) {
|
||||
//printf("runner update! %u\n", getTimeStamp());
|
||||
//dbg_printf("runnerUpdate\n");
|
||||
runnerUpdate();
|
||||
}
|
||||
else {
|
||||
if (runner.skipUpdateNow) {
|
||||
//printf("Skipped one update\n");
|
||||
runner.nextUpdateScheduled = true;
|
||||
runner.skipUpdateNow = false;
|
||||
}
|
||||
}
|
||||
|
||||
int frameTime = getTimeStamp() - frameStartTime;
|
||||
if (frameTime < 0) {
|
||||
frameTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
#define FRAME_TIME 20 //16
|
||||
// dbg_printf("frameTime = %d\n", frameTime);
|
||||
if (frameTime < FRAME_TIME) { // 1000ms/60frames = 16.(6)
|
||||
// printf("frameTime = %d\n", frameTime);
|
||||
if (runner.crashed) {
|
||||
// dbg_printf("runner.timeAfterCrashedMs +=\n");
|
||||
runner.timeAfterCrashedMs += FRAME_TIME - frameTime;
|
||||
}
|
||||
graphicsDelay(FRAME_TIME - frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
graphicsDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
28
programs/games/dino/misc.c
Normal file
28
programs/games/dino/misc.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include "misc.h"
|
||||
|
||||
int getRandomNumber(int _min, int _max) {
|
||||
return rand() % (_max - _min + 1) + _min;
|
||||
}
|
||||
|
||||
void intToStr(int num, int ndigits, char* result) {
|
||||
char num_str[16]; // 16 more than enough for int
|
||||
sprintf(num_str, "%d", num); // Convert num to a string
|
||||
if (strlen(num_str) > ndigits) {
|
||||
// Copy only the last ndigits to result
|
||||
strcpy(result, num_str + strlen(num_str) - ndigits);
|
||||
}
|
||||
else {
|
||||
// Pad the string with leading zeros until it reaches a length of ndigits
|
||||
size_t z = ndigits - strlen(num_str);
|
||||
for (size_t i = 0; i < z; i++) {
|
||||
result[i] = '0';
|
||||
}
|
||||
strcpy(result + z, num_str);
|
||||
}
|
||||
}
|
||||
|
||||
int getTimeStamp() { // in ms
|
||||
uint64_t x = 0;
|
||||
x = _ksys_get_ns_count();
|
||||
return (x/1000000);
|
||||
}
|
13
programs/games/dino/misc.h
Normal file
13
programs/games/dino/misc.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
int getRandomNumber(int _min, int _max);
|
||||
void intToStr(int num, int ndigits, char* result);
|
||||
int getTimeStamp();
|
||||
|
||||
#endif
|
156
programs/games/dino/obstacle.c
Normal file
156
programs/games/dino/obstacle.c
Normal file
@ -0,0 +1,156 @@
|
||||
#include "obstacle.h"
|
||||
|
||||
ObstacleTypeConfig obstacleTypeConfigs[3] = {
|
||||
{
|
||||
.type = CACTUS_SMALL,
|
||||
.width = 17,
|
||||
.height = 35,
|
||||
.yPos = 105,
|
||||
.multipleSpeed = 4,
|
||||
.minGap = 120,
|
||||
.minSpeed = 0,
|
||||
.collisionBoxesCount = 3,
|
||||
.collisionBoxes = {
|
||||
{.x = 0, .y = 7, .width = 5, .height = 27},
|
||||
{.x = 4, .y = 0, .width = 6, .height = 34},
|
||||
{.x = 10, .y = 4, .width = 7, .height = 14}
|
||||
},
|
||||
.numFrames = 1,
|
||||
.speedOffset = 0
|
||||
},
|
||||
{
|
||||
.type = CACTUS_LARGE,
|
||||
.width = 25,
|
||||
.height = 50,
|
||||
.yPos = 90,
|
||||
.multipleSpeed = 7,
|
||||
.minGap = 120,
|
||||
.minSpeed = 0,
|
||||
.collisionBoxesCount = 3,
|
||||
.collisionBoxes = {
|
||||
{.x = 0, .y = 12, .width = 7, .height = 38},
|
||||
{.x = 8, .y = 0, .width = 7, .height = 49},
|
||||
{.x = 13, .y = 10, .width = 10, .height = 38}
|
||||
},
|
||||
.numFrames = 1,
|
||||
.speedOffset = 0
|
||||
},
|
||||
{
|
||||
.type = PTERODACTYL,
|
||||
.width = 46,
|
||||
.height = 40,
|
||||
.yPos = -1,
|
||||
.yPosArrSize = 3,
|
||||
.yPosArr = {100, 75, 50},
|
||||
.multipleSpeed = 999,
|
||||
.minGap = 150,
|
||||
.minSpeed = 8.5,
|
||||
.collisionBoxesCount = 5,
|
||||
.collisionBoxes = {
|
||||
{.x = 15, .y = 15, .width = 16, .height = 5},
|
||||
{.x = 18, .y = 21, .width = 24, .height = 6},
|
||||
{.x = 2, .y = 14, .width = 4, .height = 3},
|
||||
{.x = 6, .y = 10, .width = 4, .height = 7},
|
||||
{.x = 10, .y = 8, .width = 6, .height = 9}
|
||||
},
|
||||
.numFrames = 2,
|
||||
.frameRate = 1000 / 6,
|
||||
.speedOffset = 0.8
|
||||
}
|
||||
};
|
||||
|
||||
int obstacleSpritePosX[3] = { ATLAS_CACTUS_SMALL_X, ATLAS_CACTUS_LARGE_X, ATLAS_PTERODACTYL_X};
|
||||
int obstacleSpritePosY[3] = { ATLAS_CACTUS_SMALL_Y, ATLAS_CACTUS_LARGE_Y, ATLAS_PTERODACTYL_Y};
|
||||
|
||||
|
||||
void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset) {
|
||||
ob->typeConfig = *otc;
|
||||
ob->gapCoefficient = gapCoefficient;
|
||||
ob->size = getRandomNumber(1, OBSTACLE_MAX_OBSTACLE_LENGTH);
|
||||
ob->remove = false;
|
||||
ob->xPos = dim_width + opt_xOffset;
|
||||
ob->yPos = 0;
|
||||
|
||||
// For animated obstacles
|
||||
ob->currentFrame = 0;
|
||||
ob->timer = 0;
|
||||
|
||||
ob->followingObstacleCreated = false;
|
||||
|
||||
if (ob->size > 1 && ob->typeConfig.multipleSpeed > speed) { // NOTE what it this?
|
||||
ob->size = 1;
|
||||
}
|
||||
ob->width = ob->typeConfig.width * ob->size;
|
||||
|
||||
if (ob->typeConfig.yPos == -1) {
|
||||
ob->yPos = ob->typeConfig.yPosArr[getRandomNumber(0, ob->typeConfig.yPosArrSize)];
|
||||
}
|
||||
else {
|
||||
ob->yPos = ob->typeConfig.yPos;
|
||||
}
|
||||
|
||||
obstacleDraw(ob);
|
||||
|
||||
// Make collision box adjustments,
|
||||
// Central box is adjusted to the size as one box.
|
||||
// ____ ______ ________
|
||||
// _| |-| _| |-| _| |-|
|
||||
// | |<->| | | |<--->| | | |<----->| |
|
||||
// | | 1 | | | | 2 | | | | 3 | |
|
||||
// |_|___|_| |_|_____|_| |_|_______|_|
|
||||
//
|
||||
|
||||
if (ob->size > 1) {
|
||||
ob->typeConfig.collisionBoxes[1].width = ob->width - ob->typeConfig.collisionBoxes[0].width - ob->typeConfig.collisionBoxes[2].width;
|
||||
ob->typeConfig.collisionBoxes[2].x = ob->width - ob->typeConfig.collisionBoxes[2].width;
|
||||
}
|
||||
|
||||
// For obstacles that go at a different speed from the horizon
|
||||
if (ob->typeConfig.speedOffset) {
|
||||
ob->typeConfig.speedOffset = (double)rand() / RAND_MAX > 0.5 ? ob->typeConfig.speedOffset : -ob->typeConfig.speedOffset;
|
||||
}
|
||||
ob->gap = obstacleGetGap(ob, ob->gapCoefficient, speed);
|
||||
}
|
||||
|
||||
void obstacleDraw(const Obstacle *ob) {
|
||||
int sourceWidth = ob->typeConfig.width;
|
||||
int sourceHeight = ob->typeConfig.height;
|
||||
int sourceX = (sourceWidth * ob->size) * (0.5 * ((double)ob->size - 1)) + obstacleSpritePosX[ob->typeConfig.type];
|
||||
if (ob->currentFrame > 0) {
|
||||
sourceX += sourceWidth*ob->currentFrame;
|
||||
}
|
||||
//dbg_printf("od ax=%u, ay=%u, dx=%u, dy=%u, w=%u, h=%u\n", sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight);
|
||||
graphicsBlitAtlasImage(sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight, false);
|
||||
}
|
||||
|
||||
void obstacleUpdate(Obstacle *ob, int deltaTime, double speed) {
|
||||
if (!ob->remove) {
|
||||
double dx = floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
|
||||
//dbg_printf("sp = %lf, ots = %lf, dx = %d, xpos = %d\n", speed, ob->typeConfig.speedOffset, (int)dx, ob->xPos - dx);
|
||||
ob->xPos -= dx;//floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
|
||||
}
|
||||
// Update frames
|
||||
if (ob->typeConfig.numFrames > 1) {
|
||||
ob->timer += deltaTime;
|
||||
if (ob->timer >= ob->typeConfig.frameRate) {
|
||||
ob->currentFrame = ob->currentFrame == ob->typeConfig.numFrames - 1 ? 0 : ob->currentFrame + 1;
|
||||
ob->timer = 0;
|
||||
}
|
||||
}
|
||||
obstacleDraw(ob);
|
||||
if (!obstacleIsVisible(ob)) {
|
||||
ob->remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
int obstacleGetGap(const Obstacle *ob, double gapCoefficient, double speed) {
|
||||
int minGap = round(ob->width * speed + ob->typeConfig.minGap * gapCoefficient);
|
||||
int maxGap = round(minGap * OBSTACLE_MAX_GAP_COEFFICIENT);
|
||||
return getRandomNumber(minGap, maxGap);
|
||||
}
|
||||
|
||||
bool obstacleIsVisible(const Obstacle* ob) {
|
||||
return ob->xPos + ob->width > 0;
|
||||
}
|
||||
|
||||
|
67
programs/games/dino/obstacle.h
Normal file
67
programs/games/dino/obstacle.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef OBSTACLE_H
|
||||
#define OBSTACLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
#include "config.h"
|
||||
#include "collisionbox.h"
|
||||
|
||||
// Coefficient for calculating the maximum gap
|
||||
#define OBSTACLE_MAX_GAP_COEFFICIENT 1.5
|
||||
|
||||
// Maximum obstacle grouping count
|
||||
#define OBSTACLE_MAX_OBSTACLE_LENGTH 3
|
||||
|
||||
typedef enum {
|
||||
CACTUS_SMALL = 0,
|
||||
CACTUS_LARGE = 1,
|
||||
PTERODACTYL = 2
|
||||
} ObstacleType;
|
||||
|
||||
extern int obstacleSpritePosX[3];
|
||||
extern int obstacleSpritePosY[3];
|
||||
|
||||
typedef struct {
|
||||
ObstacleType type;
|
||||
int width;
|
||||
int height;
|
||||
int yPos;
|
||||
int yPosArrSize;
|
||||
int yPosArr[3]; // used if yPos is -1
|
||||
int multipleSpeed;
|
||||
int minGap;
|
||||
int minSpeed;
|
||||
int collisionBoxesCount;
|
||||
CollisionBox collisionBoxes[5];
|
||||
int numFrames;
|
||||
double frameRate;
|
||||
double speedOffset;
|
||||
} ObstacleTypeConfig;
|
||||
|
||||
typedef struct {
|
||||
ObstacleTypeConfig typeConfig;
|
||||
double gapCoefficient;
|
||||
int size;
|
||||
bool remove;
|
||||
int xPos;
|
||||
int yPos;
|
||||
int width;
|
||||
int gap;
|
||||
// double speedOffset;
|
||||
int currentFrame;
|
||||
int timer;
|
||||
bool followingObstacleCreated;
|
||||
} Obstacle;
|
||||
|
||||
extern ObstacleTypeConfig obstacleTypeConfigs[3];
|
||||
|
||||
void obstacleInit(Obstacle *ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset);
|
||||
void obstacleDraw(const Obstacle* ob);
|
||||
void obstacleUpdate(Obstacle* ob, int deltaTime, double speed);
|
||||
int obstacleGetGap(const Obstacle* ob, double gapCoefficient, double speed);
|
||||
bool obstacleIsVisible(const Obstacle* ob);
|
||||
|
||||
#endif
|
333
programs/games/dino/runner.c
Normal file
333
programs/games/dino/runner.c
Normal file
@ -0,0 +1,333 @@
|
||||
#include "runner.h"
|
||||
|
||||
int aaaaaaa[10000];
|
||||
Runner runner;
|
||||
int bbbbbb[10000];
|
||||
|
||||
void runnerInit() {
|
||||
runner.distanceRan = 0;
|
||||
runner.highestScore = 0;
|
||||
runner.time = 0;
|
||||
runner.msPerFrame = 1000.0 / FPS;
|
||||
runner.currentSpeed = RUNNER_SPEED;
|
||||
runner.activated = false;
|
||||
runner.playing = false;
|
||||
runner.crashed = false;
|
||||
runner.timeAfterCrashedMs = 0;
|
||||
runner.paused = false;
|
||||
runner.inverted = false;
|
||||
runner.playingIntro = false;
|
||||
runner.isRunning = false; // is running or game stopped
|
||||
runner.invertTimer = 0;
|
||||
runner.playCount = 0;
|
||||
runner.nextUpdateScheduled = false;
|
||||
runner.skipUpdateNow = false;
|
||||
// TODO sound
|
||||
// runnerLoadImages();
|
||||
runnerAdjustDimensions();
|
||||
// setSpeed
|
||||
graphicsFillBackground(0xF7, 0xF7, 0xF7);
|
||||
|
||||
gameOverPanelInit(runner.width, runner.height);
|
||||
|
||||
horizonInit(runner.width, RUNNER_GAP_COEFFICIENT);
|
||||
distanceMeterInit(runner.width);
|
||||
trexInit();
|
||||
|
||||
// this.startListening();
|
||||
runnerUpdate();
|
||||
//window.addEventListener(Runner.events.RESIZE, this.debounceResize.bind(this));
|
||||
}
|
||||
|
||||
void runnerAdjustDimensions() {
|
||||
runner.width = DEFAULT_WIDTH;
|
||||
runner.height = RUNNER_DEFAULT_HEIGHT;
|
||||
// distance meter ...
|
||||
}
|
||||
|
||||
void runnerOnKeyDown(int key) {
|
||||
if (!runner.crashed && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
if (!runner.playing) {
|
||||
// this.loadSounds(); // TODO
|
||||
runner.playing = true;
|
||||
//printf("first jump! %u\n", getTimeStamp());
|
||||
runnerUpdate();
|
||||
runner.nextUpdateScheduled = false;
|
||||
runner.skipUpdateNow = true;
|
||||
}
|
||||
// Play sound effect and jump on starting the game for the first time.
|
||||
if (!trex.jumping && !trex.ducking) {
|
||||
// this.playSound(this.soundFx.BUTTON_PRESS); // TODO
|
||||
trexStartJump(runner.currentSpeed);
|
||||
}
|
||||
}
|
||||
if (runner.playing && !runner.crashed && key == RUNNER_KEYCODE_DUCK) {
|
||||
if (trex.jumping) {
|
||||
// Speed drop, activated only when jump key is not pressed.
|
||||
trexSetSpeedDrop();
|
||||
}
|
||||
//else if (!trex.jumping &&!trex.ducking) {
|
||||
else if (!trex.ducking) {
|
||||
// Duck
|
||||
trexSetDuck(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runnerOnKeyUp(int key) {
|
||||
if (runner.isRunning && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
trexEndJump();
|
||||
}
|
||||
else if (key == RUNNER_KEYCODE_DUCK) {
|
||||
trex.speedDrop = false;
|
||||
trexSetDuck(false);
|
||||
}
|
||||
else if (runner.crashed) {
|
||||
// Check that enough time has elapsed before allowing jump key to restart.
|
||||
|
||||
int now = getTimeStamp();
|
||||
int deltaTime = now - runner.time;
|
||||
// if (deltaTime < 0) {
|
||||
// deltaTime = DELTA_MS_DEFAULT;
|
||||
// runner.time = 0;
|
||||
// }
|
||||
|
||||
// dbg_printf(".now = %d .deltaTime = %d runner.time = %d\n", now, deltaTime, runner.time);
|
||||
if (key == RUNNER_KEYCODE_RESTART || (runner.timeAfterCrashedMs >= RUNNER_GAMEOVER_CLEAR_TIME && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2))) {
|
||||
//dbg_printf("timeAfterCrashedMs = %d\n", runner.timeAfterCrashedMs);
|
||||
runnerRestart();
|
||||
}
|
||||
}
|
||||
else if (runner.paused && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
trexReset();
|
||||
runnerPlay();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerClearCanvas() {
|
||||
graphicsFillBackground(0xF7, 0xF7, 0xF7);
|
||||
//graphicsRender();
|
||||
}
|
||||
|
||||
void runnerUpdate() {
|
||||
//dbg_printf("runnerUpdate() runner.playing = %d\n", runner.playing);
|
||||
//runner.updatePending = false;
|
||||
int now = getTimeStamp();
|
||||
//printf("now = %d\n", now);
|
||||
int deltaTime = now - (runner.time ? runner.time : 0);
|
||||
if (deltaTime < 0) {
|
||||
deltaTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
// dbg_printf("runnerUpdate() deltaTime = %d\n", deltaTime);
|
||||
runner.time = now;
|
||||
if (runner.playing) {
|
||||
//printf("runnerUpdate() %d\n", getTimeStamp());
|
||||
runnerClearCanvas();
|
||||
|
||||
if (trex.jumping) {
|
||||
trexUpdateJump(deltaTime);
|
||||
}
|
||||
|
||||
runner.runningTime += deltaTime;
|
||||
bool hasObstacles = runner.runningTime > RUNNER_CLEAR_TIME;
|
||||
|
||||
// First jump triggers the intro.
|
||||
if (trex.jumpCount == 1 && !runner.playingIntro) {
|
||||
//printf("trex.jumpCount = %d\n", trex.jumpCount);
|
||||
runnerPlayIntro();
|
||||
}
|
||||
|
||||
// The horizon doesn't move until the intro is over.
|
||||
if (runner.playingIntro) {
|
||||
horizonUpdate(0, runner.currentSpeed, hasObstacles, false);
|
||||
}
|
||||
else {
|
||||
deltaTime = !runner.activated ? 0 : deltaTime;
|
||||
horizonUpdate(deltaTime, runner.currentSpeed, hasObstacles, runner.inverted);
|
||||
}
|
||||
|
||||
// Check for collisions.
|
||||
bool collision = hasObstacles && runnerCheckForCollision(horizon.obstacles->head->data);
|
||||
|
||||
if (!collision) {
|
||||
runner.distanceRan += runner.currentSpeed * deltaTime / runner.msPerFrame;
|
||||
|
||||
if (runner.currentSpeed < RUNNER_MAX_SPEED) {
|
||||
runner.currentSpeed += RUNNER_ACCELERATION;
|
||||
}
|
||||
}
|
||||
else {
|
||||
runnerGameOver();
|
||||
}
|
||||
|
||||
bool playAchievementSound = distanceMeterUpdate(deltaTime, (int)ceil(runner.distanceRan));
|
||||
|
||||
if (playAchievementSound) {
|
||||
//this.playSound(this.soundFx.SCORE); // TODO
|
||||
}
|
||||
|
||||
/*// Night mode.
|
||||
if (this.invertTimer > this.config.INVERT_FADE_DURATION) {
|
||||
this.invertTimer = 0;
|
||||
this.invertTrigger = false;
|
||||
this.invert();
|
||||
}
|
||||
else if (this.invertTimer) {
|
||||
this.invertTimer += deltaTime;
|
||||
}
|
||||
else {
|
||||
var actualDistance =
|
||||
this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));
|
||||
|
||||
if (actualDistance > 0) {
|
||||
this.invertTrigger = !(actualDistance %
|
||||
this.config.INVERT_DISTANCE);
|
||||
|
||||
if (this.invertTrigger&& this.invertTimer == = 0) {
|
||||
this.invertTimer += deltaTime;
|
||||
this.invert();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
runner.nextUpdateScheduled = false;//
|
||||
if (runner.playing || (!runner.activated && trex.blinkCount < RUNNER_MAX_BLINK_COUNT)) {
|
||||
trexUpdate(deltaTime, -1);
|
||||
runner.nextUpdateScheduled = true;
|
||||
}
|
||||
|
||||
graphicsRender(); // blit all drawn to the screen
|
||||
//printf("runner update end\n\n");
|
||||
}
|
||||
|
||||
void runnerGameOver() {
|
||||
// this.playSound(this.soundFx.HIT); // TODO
|
||||
runnerStop();
|
||||
runner.crashed = true;
|
||||
distanceMeter.achievement = false;
|
||||
trexUpdate(100, TREX_STATUS_CRASHED);
|
||||
|
||||
// Game over panel
|
||||
gameOverPanelDraw();
|
||||
// Update the high score
|
||||
if (runner.distanceRan > runner.highestScore) {
|
||||
runner.highestScore = (int)ceil(runner.distanceRan);
|
||||
distanceMeterSetHighScore(runner.highestScore);
|
||||
}
|
||||
// Reset the time clock
|
||||
runner.time = getTimeStamp();
|
||||
}
|
||||
|
||||
void runnerStop() {
|
||||
runner.playing = false;
|
||||
runner.paused = true;
|
||||
runner.isRunning = false;
|
||||
}
|
||||
|
||||
void runnerPlay() {
|
||||
if (!runner.crashed) {
|
||||
runner.playing = true;
|
||||
runner.paused = false;
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
runner.time = getTimeStamp();
|
||||
runnerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerRestart() {
|
||||
if (!runner.isRunning) {
|
||||
runner.playCount++;
|
||||
runner.runningTime = 0;
|
||||
runner.playing = true;
|
||||
runner.crashed = false;
|
||||
runner.timeAfterCrashedMs = 0;
|
||||
runner.distanceRan = 0;
|
||||
runner.currentSpeed = RUNNER_SPEED;
|
||||
runner.time = getTimeStamp();
|
||||
runnerClearCanvas();
|
||||
distanceMeterReset(runner.highestScore);
|
||||
horizonReset();
|
||||
trexReset();
|
||||
//this.playSound(this.soundFx.BUTTON_PRESS);
|
||||
//this.invert(true);
|
||||
runner.isRunning = true;
|
||||
runnerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerPlayIntro() {
|
||||
//printf("runnerPlayIntro()\n");
|
||||
if (!runner.activated && !runner.crashed) {
|
||||
runner.playingIntro = true;
|
||||
trex.playingIntro = true;
|
||||
runner.playing = true;
|
||||
runner.activated = true;
|
||||
}
|
||||
else if (runner.crashed) {
|
||||
runnerRestart();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerStartGame() {
|
||||
runner.runningTime = 0;
|
||||
runner.playingIntro = false;
|
||||
trex.playingIntro = false;
|
||||
runner.playCount++;
|
||||
runner.isRunning = true;
|
||||
}
|
||||
|
||||
CollisionBox createAdjustedCollisionBox(CollisionBox box, CollisionBox adjustment) {
|
||||
return (CollisionBox){ .x = box.x + adjustment.x, .y = box.y + adjustment.y, .width = box.width, .height = box.height };
|
||||
}
|
||||
|
||||
// Returns whether boxes intersected
|
||||
bool boxCompare(CollisionBox tRexBox, CollisionBox obstacleBox) {
|
||||
// Axis-Aligned Bounding Box method.
|
||||
return (tRexBox.x < obstacleBox.x + obstacleBox.width &&
|
||||
tRexBox.x + tRexBox.width > obstacleBox.x &&
|
||||
tRexBox.y < obstacleBox.y + obstacleBox.height &&
|
||||
tRexBox.height + tRexBox.y > obstacleBox.y);
|
||||
}
|
||||
|
||||
bool runnerCheckForCollision(const Obstacle* obstacle) {
|
||||
// Adjustments are made to the bounding box as there is a 1 pixel white
|
||||
// border around the t-rex and obstacles.
|
||||
CollisionBox tRexBox = {
|
||||
.x = trex.xPos + 1,
|
||||
.y = trex.yPos + 1,
|
||||
.width = TREX_WIDTH - 2,
|
||||
.height = TREX_HEIGHT - 2 };
|
||||
|
||||
CollisionBox obstacleBox = {
|
||||
.x = obstacle->xPos + 1,
|
||||
.y = obstacle->yPos + 1,
|
||||
.width = obstacle->typeConfig.width * obstacle->size - 2,
|
||||
.height = obstacle->typeConfig.height - 2 };
|
||||
|
||||
// Simple outer bounds check.
|
||||
if (boxCompare(tRexBox, obstacleBox)) {
|
||||
CollisionBox* tRexCollisionBoxes = &trexDuckingCollisionBox;
|
||||
int tRexCollisionBoxesCount = 1;
|
||||
if (!trex.ducking) {
|
||||
tRexCollisionBoxes = trexRunningCollisionBox;
|
||||
tRexCollisionBoxesCount = 6;
|
||||
}
|
||||
|
||||
// Detailed axis aligned box check.
|
||||
for (int t = 0; t < tRexCollisionBoxesCount; t++) {
|
||||
for (int i = 0; i < obstacle->typeConfig.collisionBoxesCount; i++) {
|
||||
// Adjust the box to actual positions.
|
||||
CollisionBox adjTrexBox = createAdjustedCollisionBox(tRexCollisionBoxes[t], tRexBox);
|
||||
CollisionBox adjObstacleBox = createAdjustedCollisionBox(obstacle->typeConfig.collisionBoxes[i], obstacleBox);
|
||||
|
||||
if (boxCompare(adjTrexBox, adjObstacleBox)) {
|
||||
return true;// [adjTrexBox, adjObstacleBox] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
91
programs/games/dino/runner.h
Normal file
91
programs/games/dino/runner.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef RUNNER_H
|
||||
#define RUNNER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
#include "ulist.h"
|
||||
#include "graphics.h"
|
||||
#include "horizon.h"
|
||||
#include "distance_meter.h"
|
||||
#include "game_over_panel.h"
|
||||
#include "trex.h"
|
||||
|
||||
#define RUNNER_DEFAULT_HEIGHT 150
|
||||
|
||||
#define RUNNER_ACCELERATION 0.001
|
||||
#define RUNNER_BG_CLOUD_SPEED 0.2
|
||||
#define RUNNER_BOTTOM_PAD 10
|
||||
#define RUNNER_CLEAR_TIME 3000
|
||||
#define RUNNER_CLOUD_FREQUENCY 0.5
|
||||
#define RUNNER_GAMEOVER_CLEAR_TIME 750
|
||||
#define RUNNER_GAP_COEFFICIENT 0.6
|
||||
#define RUNNER_GRAVITY 0.6
|
||||
#define RUNNER_INITIAL_JUMP_VELOCITY 12
|
||||
#define RUNNER_INVERT_FADE_DURATION 12000
|
||||
#define RUNNER_INVERT_DISTANCE 700
|
||||
#define RUNNER_MAX_BLINK_COUNT 3
|
||||
#define RUNNER_MAX_CLOUDS 6
|
||||
#define RUNNER_MAX_OBSTACLE_LENGTH 3
|
||||
#define RUNNER_MAX_OBSTACLE_DUPLICATION 2
|
||||
#define RUNNER_MAX_SPEED 13.0
|
||||
#define RUNNER_MIN_JUMP_HEIGHT 35
|
||||
#define RUNNER_MOBILE_SPEED_COEFFICIENT 1.2
|
||||
#define RUNNER_SPEED 6.0
|
||||
#define RUNNER_SPEED_DROP_COEFFICIENT 3
|
||||
|
||||
#define RUNNER_KEYCODE_JUMP_1 82
|
||||
#define RUNNER_KEYCODE_JUMP_2 32
|
||||
#define RUNNER_KEYCODE_DUCK 81
|
||||
#define RUNNER_KEYCODE_RESTART 13
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
double distanceRan;
|
||||
int highestScore;
|
||||
int time;
|
||||
int runningTime;
|
||||
double msPerFrame;
|
||||
double azazzaza; //
|
||||
double currentSpeed;
|
||||
// Ulist* obstacles;
|
||||
bool activated;
|
||||
bool playing;
|
||||
bool crashed;
|
||||
int timeAfterCrashedMs;
|
||||
bool paused;
|
||||
bool inverted;
|
||||
bool invertTimer;
|
||||
bool playingIntro;
|
||||
bool isRunning;
|
||||
// resizeTimerId_
|
||||
int playCount;
|
||||
// soundFx
|
||||
// audioContext
|
||||
// images
|
||||
// imagesLoaded
|
||||
bool nextUpdateScheduled;
|
||||
bool skipUpdateNow;
|
||||
} Runner;
|
||||
|
||||
extern Runner runner;
|
||||
|
||||
void runnerInit();
|
||||
void runnerAdjustDimensions();
|
||||
//void runnerLoadImages();
|
||||
|
||||
void runnerClearCanvas();
|
||||
|
||||
void runnerPlayIntro();
|
||||
void runnerStartGame();
|
||||
void runnerUpdate();
|
||||
void runnerOnKeyDown(int key);
|
||||
void runnerOnKeyUp(int key);
|
||||
void runnerGameOver();
|
||||
void runnerStop();
|
||||
void runnerPlay();
|
||||
void runnerRestart();
|
||||
|
||||
bool runnerCheckForCollision(const Obstacle *obstacle);
|
||||
|
||||
#endif
|
169
programs/games/dino/sprites.h
Normal file
169
programs/games/dino/sprites.h
Normal file
@ -0,0 +1,169 @@
|
||||
// Original chrome dino sprite pack
|
||||
static const char sprites100[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
|
||||
0x00, 0x00, 0x04, 0xd1, 0x00, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x23, 0xfc,
|
||||
0x41, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x76, 0x93, 0xcd, 0x38, 0x00,
|
||||
0x00, 0x0a, 0x0e, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xec, 0x9d, 0x5b, 0x76, 0xa4, 0xb8, 0x16,
|
||||
0x44, 0x83, 0xbb, 0xb8, 0x0f, 0x4d, 0x84, 0xa1, 0xd8, 0x03, 0x80, 0x4f, 0x0d, 0x4f, 0x9f, 0xa9,
|
||||
0x01, 0x54, 0x0d, 0x85, 0x89, 0xe8, 0x93, 0xae, 0x57, 0xac, 0xab, 0xaa, 0x68, 0xf2, 0x58, 0x2d,
|
||||
0xd2, 0x98, 0xf4, 0xd9, 0xbd, 0x3a, 0x13, 0x9f, 0x07, 0x95, 0x18, 0x57, 0x38, 0x24, 0x01, 0x05,
|
||||
0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xe7, 0xc3, 0x31, 0xe0, 0x3b, 0x05, 0xf7, 0x08, 0x38, 0x8e,
|
||||
0x15, 0xc0, 0x84, 0x83, 0x29, 0x08, 0x6f, 0x2b, 0x43, 0xb8, 0x1f, 0xd8, 0x80, 0xa1, 0xb7, 0x85,
|
||||
0x65, 0x2c, 0x7c, 0x58, 0x82, 0xb4, 0x76, 0xac, 0xf8, 0xce, 0xd4, 0x11, 0x83, 0x55, 0xdd, 0x10,
|
||||
0x23, 0x5f, 0x5f, 0xf0, 0x93, 0x19, 0x40, 0xe6, 0x36, 0x32, 0x43, 0x3f, 0xa3, 0x33, 0xb8, 0xc9,
|
||||
0xca, 0x2a, 0xc4, 0x34, 0x63, 0xe0, 0x26, 0xcb, 0x19, 0xe2, 0xae, 0xea, 0xe6, 0xc7, 0x52, 0xa0,
|
||||
0x84, 0x0b, 0xd6, 0x5e, 0x80, 0x11, 0x00, 0x4a, 0xc4, 0x3d, 0x4a, 0x40, 0x07, 0xf2, 0xb3, 0xbc,
|
||||
0xae, 0x98, 0x70, 0x02, 0x25, 0xf2, 0x50, 0xf6, 0x02, 0xdb, 0x02, 0x6c, 0x43, 0x4f, 0x4b, 0x55,
|
||||
0xc6, 0xc2, 0xa3, 0x13, 0x4a, 0x7b, 0xc7, 0x84, 0xd3, 0x98, 0x80, 0x15, 0x77, 0x98, 0xa9, 0x64,
|
||||
0x94, 0xa0, 0xea, 0x3d, 0x4b, 0x21, 0x31, 0x42, 0x33, 0xb2, 0xec, 0xe5, 0x39, 0x71, 0x46, 0x5b,
|
||||
0xd0, 0x10, 0x4b, 0x40, 0xbf, 0x96, 0xff, 0xd0, 0x31, 0x6a, 0xda, 0x84, 0xe3, 0x28, 0x88, 0xa6,
|
||||
0x4b, 0xe3, 0x51, 0xf2, 0x50, 0x24, 0x40, 0x75, 0xc2, 0xb2, 0x0d, 0x1d, 0x2d, 0x55, 0x19, 0x0b,
|
||||
0x0f, 0x4f, 0xa8, 0x57, 0xb4, 0x3b, 0xc8, 0xba, 0x1f, 0x9b, 0xac, 0x3a, 0xac, 0xa6, 0xdd, 0xae,
|
||||
0x63, 0x54, 0x2f, 0xa3, 0x4e, 0xc9, 0xaa, 0x4c, 0xb4, 0x67, 0x14, 0xba, 0x2c, 0x59, 0xd9, 0x64,
|
||||
0x87, 0x6e, 0xc9, 0x7e, 0x33, 0xde, 0xc1, 0xa1, 0x45, 0xfc, 0x4e, 0xba, 0x72, 0xad, 0xf1, 0x9b,
|
||||
0x24, 0x9f, 0xac, 0x68, 0x14, 0x34, 0x5b, 0xd2, 0x3a, 0x8e, 0x7c, 0x45, 0xfd, 0x93, 0xbe, 0xe2,
|
||||
0x7a, 0xa8, 0xeb, 0xa1, 0x90, 0x9d, 0xea, 0x37, 0xdb, 0x99, 0x1e, 0x52, 0x3b, 0x61, 0xed, 0xb1,
|
||||
0x69, 0x5f, 0x7f, 0x0c, 0x3b, 0xa9, 0x5b, 0x33, 0xe6, 0x4c, 0x69, 0xe3, 0x98, 0x11, 0x32, 0x12,
|
||||
0xcd, 0x8c, 0xcd, 0xf5, 0x68, 0xb2, 0xee, 0xc8, 0x6e, 0xca, 0x3e, 0x1d, 0x23, 0xde, 0x89, 0x49,
|
||||
0x05, 0xee, 0x38, 0xc4, 0xa5, 0x59, 0xca, 0xa4, 0x81, 0x0d, 0x83, 0x4a, 0x55, 0x5d, 0x51, 0x22,
|
||||
0x1b, 0x59, 0xb5, 0x6c, 0xda, 0xf2, 0x78, 0xd4, 0x2b, 0xda, 0x74, 0x3b, 0x34, 0x8d, 0x31, 0x3a,
|
||||
0xdd, 0x8f, 0x4d, 0x58, 0xed, 0xba, 0xaf, 0x7c, 0x7d, 0x31, 0x4d, 0xc0, 0xcc, 0x31, 0xa4, 0xd6,
|
||||
0x64, 0x16, 0x66, 0xed, 0x81, 0x86, 0xde, 0x95, 0x68, 0xfc, 0xc4, 0x5e, 0xb9, 0x76, 0xd6, 0x08,
|
||||
0xf2, 0x65, 0x15, 0xcd, 0x3e, 0x72, 0x85, 0x23, 0xcf, 0x93, 0x26, 0x74, 0x4a, 0x2c, 0x41, 0x03,
|
||||
0xdb, 0x82, 0x4d, 0xa5, 0xaa, 0xaa, 0x28, 0x11, 0xb1, 0xfc, 0x2e, 0x68, 0x58, 0xb4, 0xa5, 0x05,
|
||||
0x1d, 0x3e, 0x3e, 0x9e, 0x09, 0xe7, 0x23, 0x36, 0xed, 0x85, 0x72, 0x76, 0x9f, 0x2c, 0x5f, 0x8a,
|
||||
0x7e, 0x49, 0x41, 0x9e, 0xeb, 0xad, 0x53, 0xb9, 0x61, 0x39, 0x63, 0xbf, 0x1d, 0xb5, 0xc0, 0xd2,
|
||||
0x5f, 0x7b, 0xbe, 0xa2, 0xa5, 0x88, 0x36, 0x32, 0xe6, 0x46, 0x6f, 0xb0, 0x4e, 0xc0, 0x54, 0x25,
|
||||
0x6a, 0x4a, 0xd3, 0xaa, 0x4a, 0x69, 0x76, 0x69, 0x25, 0xd6, 0xe6, 0x86, 0x81, 0xff, 0x2d, 0xc0,
|
||||
0x72, 0xab, 0xa4, 0x6a, 0xf8, 0xb3, 0x02, 0xfb, 0xb0, 0xe5, 0xf8, 0xe1, 0x63, 0xbf, 0x38, 0xf6,
|
||||
0x39, 0xb4, 0x49, 0x63, 0xfb, 0x4e, 0x6b, 0x5a, 0xff, 0xb9, 0x4b, 0xc3, 0xcb, 0xd7, 0x7d, 0x41,
|
||||
0xa3, 0xf3, 0xe2, 0xeb, 0x4c, 0x3f, 0xa6, 0x43, 0xca, 0xcc, 0x6c, 0x3d, 0xe4, 0x9c, 0x7f, 0x7c,
|
||||
0xa5, 0xcb, 0xa6, 0xce, 0x7d, 0x16, 0xdc, 0x7a, 0x6b, 0x4f, 0x60, 0x44, 0xaf, 0xa4, 0x09, 0xf6,
|
||||
0xd0, 0x64, 0x92, 0xd1, 0xe7, 0xd5, 0x28, 0xe1, 0x9c, 0xe1, 0xa3, 0x50, 0x82, 0x88, 0xe3, 0xd5,
|
||||
0x99, 0xf3, 0xbd, 0x31, 0x27, 0x93, 0x1a, 0xb3, 0x39, 0x57, 0xc6, 0x96, 0x53, 0xf7, 0xcb, 0xda,
|
||||
0xa7, 0x67, 0x44, 0xb7, 0xa4, 0xcd, 0xa6, 0x2b, 0x98, 0xcc, 0xc1, 0x07, 0x29, 0x88, 0xc6, 0xf5,
|
||||
0x65, 0x5a, 0x9d, 0x90, 0x10, 0x0d, 0x97, 0x56, 0x82, 0x15, 0xb0, 0x5b, 0x74, 0xe4, 0x7a, 0x3e,
|
||||
0xfc, 0x20, 0xb6, 0x38, 0xae, 0xf6, 0xf9, 0x31, 0xeb, 0x48, 0xeb, 0x5c, 0xda, 0x6a, 0xd7, 0x91,
|
||||
0x3c, 0xcb, 0x08, 0x73, 0xff, 0x6b, 0x5b, 0xcc, 0x64, 0x10, 0xc1, 0x0e, 0x1b, 0xe7, 0xd6, 0x5f,
|
||||
0x7b, 0xb6, 0xa2, 0xa5, 0x5a, 0xd2, 0x12, 0x10, 0x8f, 0xf2, 0x66, 0x46, 0xd5, 0x49, 0x73, 0x67,
|
||||
0x6d, 0x2d, 0x3a, 0x0c, 0x3d, 0x1f, 0x0e, 0xa1, 0xaf, 0x30, 0x8b, 0x66, 0x2c, 0x8e, 0x6e, 0xa0,
|
||||
0xa4, 0x55, 0xab, 0x99, 0x14, 0x2d, 0x0e, 0x3c, 0xbf, 0x27, 0xa9, 0x4a, 0xe4, 0xff, 0x31, 0xcd,
|
||||
0xd6, 0x0a, 0x29, 0x39, 0xf9, 0x33, 0x9e, 0x01, 0xf7, 0x7e, 0xff, 0x12, 0x41, 0xab, 0xb6, 0xd2,
|
||||
0x3b, 0x4c, 0x43, 0x4f, 0x55, 0x51, 0x29, 0xb1, 0x41, 0x44, 0xb5, 0x3a, 0xc6, 0x52, 0x0c, 0x05,
|
||||
0x92, 0xc0, 0xa3, 0x45, 0xab, 0x94, 0xb2, 0x97, 0x30, 0x3a, 0x3e, 0x11, 0x5f, 0xf8, 0xea, 0x38,
|
||||
0xc7, 0x79, 0xb4, 0xa4, 0x4b, 0x98, 0x29, 0x76, 0xf8, 0xb3, 0x95, 0x8b, 0x00, 0x06, 0x93, 0xd6,
|
||||
0x5c, 0x1f, 0x73, 0x72, 0xab, 0xe8, 0x20, 0xd9, 0xe8, 0x90, 0xfa, 0x86, 0xb5, 0x02, 0x59, 0x58,
|
||||
0x66, 0x8c, 0x71, 0x6b, 0xcc, 0xd9, 0x35, 0xee, 0x9c, 0x56, 0x8d, 0xd1, 0xa5, 0xfd, 0x88, 0xbd,
|
||||
0x02, 0xe0, 0x6b, 0x06, 0xa0, 0x1b, 0xba, 0xc9, 0xaf, 0x18, 0xd3, 0x42, 0xc9, 0x6a, 0x5b, 0x86,
|
||||
0xf3, 0xd4, 0xf3, 0x68, 0xf5, 0x68, 0x33, 0x22, 0xf5, 0x0d, 0x38, 0xa7, 0xc6, 0x8b, 0x69, 0x0b,
|
||||
0x62, 0xc3, 0xba, 0x65, 0x5d, 0x9d, 0x00, 0xed, 0x3c, 0x03, 0x4a, 0x88, 0xce, 0xfc, 0x6b, 0x02,
|
||||
0x88, 0x09, 0xc4, 0xea, 0xa0, 0x06, 0x86, 0x0e, 0x39, 0xfd, 0xe0, 0x2e, 0xed, 0xcb, 0x2b, 0xba,
|
||||
0x71, 0x9c, 0x11, 0x4a, 0x44, 0x37, 0x93, 0x6c, 0x5d, 0x80, 0xe5, 0x51, 0x8e, 0x8c, 0x89, 0xee,
|
||||
0xbb, 0x50, 0x63, 0xd3, 0x3e, 0x28, 0x8e, 0xd7, 0x19, 0x74, 0xbe, 0x02, 0xd8, 0xbd, 0x7b, 0x7c,
|
||||
0xde, 0x09, 0x66, 0xbe, 0x4b, 0xb1, 0xee, 0x47, 0xba, 0x59, 0xd1, 0xb3, 0xcf, 0xb9, 0x8a, 0x9a,
|
||||
0x24, 0x90, 0x33, 0x6b, 0x9f, 0x98, 0xf1, 0x28, 0x41, 0x4b, 0xfd, 0x77, 0x67, 0xee, 0xde, 0x31,
|
||||
0x1a, 0xcc, 0x6a, 0x9c, 0xef, 0xd2, 0x54, 0x42, 0x34, 0x71, 0x82, 0x1a, 0x19, 0x4f, 0xd1, 0x68,
|
||||
0x88, 0x99, 0xe3, 0xce, 0xf6, 0xd8, 0xb4, 0x32, 0x46, 0x39, 0x73, 0x9c, 0xa3, 0x15, 0x2d, 0xe2,
|
||||
0x13, 0x32, 0x6c, 0x0b, 0x9c, 0x13, 0x79, 0xe5, 0xa0, 0x93, 0xce, 0x48, 0x98, 0x79, 0xbf, 0xa7,
|
||||
0x26, 0xf2, 0x0c, 0x05, 0x5a, 0xb9, 0xe7, 0xef, 0x66, 0xa3, 0xd6, 0xdc, 0x67, 0xbd, 0x1f, 0xb9,
|
||||
0x46, 0xbc, 0xe8, 0x5f, 0x2f, 0x24, 0x04, 0xe0, 0x12, 0xb5, 0x60, 0x6d, 0xc3, 0xf7, 0xe8, 0x1a,
|
||||
0xf7, 0x75, 0x36, 0x7c, 0x97, 0xfa, 0x1d, 0x9a, 0xf8, 0xb5, 0xd0, 0x50, 0x7d, 0x97, 0x28, 0x01,
|
||||
0x53, 0xd2, 0xe2, 0xe9, 0x8b, 0xd6, 0xf2, 0xcd, 0x78, 0x36, 0xbe, 0xbc, 0xf2, 0xf5, 0x9e, 0x9e,
|
||||
0x01, 0x99, 0xaa, 0x21, 0x49, 0xc7, 0xa1, 0xa2, 0x7d, 0x3e, 0x52, 0x28, 0x7f, 0x06, 0x80, 0x61,
|
||||
0x03, 0x16, 0xbb, 0xa5, 0xe2, 0xb6, 0xe0, 0x04, 0xea, 0xf5, 0x81, 0x82, 0x27, 0xe1, 0x95, 0xaf,
|
||||
0xd7, 0xa7, 0x70, 0xa5, 0xaa, 0x3a, 0x45, 0x11, 0x24, 0x5d, 0xb7, 0x96, 0x7e, 0x58, 0x22, 0x24,
|
||||
0x43, 0xaf, 0x2f, 0x1c, 0xd0, 0x40, 0x5f, 0x2b, 0x19, 0x1f, 0x70, 0xa6, 0xba, 0xe7, 0xe1, 0x22,
|
||||
0x74, 0x6e, 0xac, 0x26, 0xa0, 0xbc, 0xb9, 0x3a, 0x40, 0xd5, 0xe9, 0x6f, 0x03, 0x03, 0x36, 0xfa,
|
||||
0x2e, 0xbb, 0xe5, 0x67, 0xfd, 0xf2, 0xde, 0x56, 0x8d, 0xeb, 0x03, 0x4f, 0x38, 0x3f, 0x30, 0x18,
|
||||
0x8b, 0x00, 0xed, 0xcc, 0x1d, 0x63, 0x20, 0x1d, 0xc9, 0x9a, 0xfb, 0x9c, 0xd1, 0x8a, 0xb3, 0x41,
|
||||
0x19, 0x3a, 0x5b, 0x47, 0x7c, 0x2e, 0x12, 0x10, 0xf6, 0x03, 0xe4, 0x36, 0x14, 0xa9, 0x10, 0x68,
|
||||
0xeb, 0xd8, 0x72, 0x96, 0xe1, 0x7c, 0x8e, 0xbb, 0x39, 0xed, 0x87, 0x1f, 0xcc, 0xfb, 0xc5, 0x7f,
|
||||
0x5b, 0x9f, 0xbb, 0xfe, 0xf4, 0x59, 0xf7, 0x20, 0x11, 0x43, 0x82, 0xf9, 0x6b, 0x5f, 0x08, 0x20,
|
||||
0x17, 0xad, 0x25, 0xb3, 0x75, 0xf3, 0xfa, 0x06, 0x60, 0xd8, 0xd1, 0x1f, 0x0c, 0x87, 0xb7, 0xaa,
|
||||
0xa2, 0x25, 0x28, 0xfd, 0x47, 0x6e, 0x73, 0x67, 0x9e, 0x4c, 0xed, 0x48, 0xaa, 0xea, 0xed, 0xea,
|
||||
0x82, 0x50, 0xc5, 0xd8, 0xa9, 0x81, 0x0a, 0xaa, 0x93, 0x56, 0xa8, 0x4d, 0x3b, 0x46, 0xd0, 0x4a,
|
||||
0x9f, 0xa0, 0xc5, 0x12, 0x64, 0x57, 0xd7, 0xe2, 0xeb, 0xcb, 0x8f, 0xff, 0x3f, 0x13, 0xce, 0x06,
|
||||
0x1d, 0xde, 0xdc, 0xb0, 0xf5, 0xb4, 0x0e, 0xa8, 0x15, 0x2d, 0xa6, 0x67, 0x5d, 0xf7, 0x0c, 0x25,
|
||||
0x1a, 0x81, 0x8a, 0x1b, 0x30, 0xec, 0xb4, 0xc4, 0x7b, 0x2d, 0x1d, 0x44, 0xb4, 0x43, 0x69, 0xe7,
|
||||
0xcd, 0x9d, 0xd7, 0x3e, 0x63, 0x2f, 0x7c, 0x86, 0xad, 0xce, 0xfd, 0xcb, 0xcd, 0xe9, 0x4a, 0xc6,
|
||||
0xc1, 0x64, 0x7a, 0xae, 0x36, 0x5b, 0x97, 0x65, 0xde, 0x43, 0x7e, 0xd7, 0x8a, 0x6d, 0xb8, 0x5a,
|
||||
0x2d, 0xcf, 0x8e, 0x9e, 0x0a, 0x75, 0xb5, 0x4b, 0x25, 0x51, 0x4b, 0xc3, 0xbd, 0xed, 0x5d, 0xad,
|
||||
0x23, 0xee, 0x48, 0x5a, 0x04, 0xda, 0x8f, 0xfc, 0x00, 0x82, 0xfa, 0xae, 0xca, 0x42, 0x86, 0xb6,
|
||||
0xea, 0x66, 0x49, 0x1b, 0xd0, 0xde, 0x72, 0x84, 0xd6, 0xb6, 0x13, 0x70, 0x7d, 0xe4, 0x19, 0xb6,
|
||||
0xbc, 0xdf, 0xbc, 0x9b, 0xf9, 0x9e, 0xde, 0x51, 0x3d, 0x59, 0xa1, 0xa9, 0xdc, 0xb6, 0xcf, 0x3c,
|
||||
0x37, 0x3f, 0xbb, 0xd5, 0x59, 0xa0, 0x91, 0x5b, 0x67, 0xeb, 0xa8, 0x0a, 0xf6, 0x8c, 0x84, 0x02,
|
||||
0x44, 0x0d, 0x34, 0xb6, 0xc4, 0xe3, 0xbf, 0x4d, 0xdc, 0xe9, 0xf9, 0x7b, 0x3a, 0x0b, 0x79, 0x86,
|
||||
0xed, 0xf5, 0xe1, 0x9d, 0x79, 0x51, 0xe2, 0x09, 0xf1, 0xe2, 0xb5, 0xd4, 0xed, 0xd9, 0x9a, 0xfc,
|
||||
0x54, 0xe5, 0xd1, 0x84, 0xb6, 0xf5, 0xb7, 0x8e, 0x8f, 0x3b, 0x53, 0xc7, 0xa3, 0x4e, 0x50, 0x5d,
|
||||
0x9a, 0x56, 0xb3, 0x44, 0x7b, 0xf6, 0xd9, 0x6b, 0x89, 0xba, 0xfa, 0x79, 0xae, 0x10, 0x95, 0x00,
|
||||
0x6e, 0x71, 0x4f, 0xd7, 0x9c, 0x47, 0xfb, 0xfe, 0xdf, 0x1d, 0x4f, 0xc5, 0x60, 0x6e, 0x8b, 0x1b,
|
||||
0xe4, 0xa6, 0x54, 0xbe, 0x5b, 0x9a, 0x71, 0x59, 0xfc, 0x7a, 0x34, 0x27, 0x85, 0x8f, 0xe0, 0xd2,
|
||||
0xb8, 0x28, 0xc0, 0xad, 0x4b, 0xbb, 0xb4, 0xa7, 0xf0, 0x68, 0xf6, 0x78, 0x27, 0x5d, 0xb7, 0xd6,
|
||||
0x5e, 0x75, 0x6e, 0xfc, 0x37, 0x0d, 0x74, 0x67, 0xfd, 0xad, 0x18, 0x1f, 0x79, 0xa6, 0xfa, 0xb1,
|
||||
0x67, 0xd1, 0xd4, 0xa5, 0xd9, 0xd5, 0x9d, 0x24, 0x63, 0xbf, 0xa5, 0xde, 0xb2, 0x13, 0xa1, 0x00,
|
||||
0x88, 0x9a, 0x20, 0xf6, 0x53, 0xdc, 0xb8, 0x15, 0xea, 0x45, 0x68, 0x79, 0xb8, 0xe2, 0x3a, 0x49,
|
||||
0x8c, 0x34, 0xc6, 0x94, 0xe9, 0x9f, 0xc5, 0x56, 0xc6, 0x1c, 0xc7, 0x3d, 0xda, 0x79, 0x04, 0x5b,
|
||||
0xf3, 0xeb, 0xad, 0x14, 0x8a, 0x26, 0x2a, 0xa3, 0x17, 0x80, 0xa2, 0x1d, 0xaa, 0x81, 0x36, 0xa1,
|
||||
0x2e, 0x2c, 0xfc, 0x43, 0x2e, 0xc1, 0x8b, 0xff, 0xec, 0x5c, 0xbc, 0x56, 0xaf, 0x6c, 0xba, 0x61,
|
||||
0xe9, 0x6f, 0x3d, 0x4d, 0xd1, 0xc2, 0xc3, 0x9c, 0x19, 0x09, 0x6d, 0xb3, 0x5e, 0x08, 0x1f, 0x7b,
|
||||
0x84, 0xaa, 0x71, 0xcd, 0xa8, 0x06, 0x16, 0x18, 0x48, 0x07, 0x3e, 0x11, 0x8e, 0x33, 0x1a, 0x13,
|
||||
0x39, 0xfe, 0xd7, 0xa2, 0x77, 0x4a, 0x2c, 0x05, 0x26, 0x9a, 0x04, 0x2d, 0xc5, 0xfe, 0xf3, 0xc0,
|
||||
0x8e, 0xfa, 0x71, 0xb1, 0xd0, 0xf1, 0xe4, 0x3a, 0x75, 0x8e, 0x3b, 0x27, 0x23, 0xb6, 0x3e, 0xf7,
|
||||
0x98, 0x53, 0xe7, 0x3f, 0x9e, 0xae, 0x96, 0x64, 0xcc, 0x1f, 0xdd, 0xa5, 0x8d, 0xb0, 0x25, 0x2d,
|
||||
0x05, 0x3d, 0xf2, 0xc7, 0xd3, 0xfc, 0x2c, 0x8f, 0xf0, 0x21, 0x25, 0x2d, 0x05, 0x26, 0xe4, 0xda,
|
||||
0x58, 0xe3, 0xdb, 0x1d, 0x61, 0x5b, 0x37, 0xff, 0x55, 0x74, 0x25, 0x12, 0xc2, 0xd3, 0xd6, 0xe6,
|
||||
0x0f, 0x35, 0x8f, 0x66, 0x8c, 0x65, 0x42, 0xc3, 0x91, 0xbb, 0x4b, 0x13, 0xe1, 0x92, 0x04, 0xa3,
|
||||
0x82, 0x74, 0x68, 0x82, 0x51, 0x1b, 0x55, 0x4d, 0x71, 0x69, 0xa7, 0xb2, 0x82, 0xb8, 0x4b, 0x73,
|
||||
0x97, 0x76, 0xeb, 0x69, 0x55, 0x45, 0x43, 0xe8, 0x3f, 0xf2, 0x7e, 0x9e, 0x42, 0x29, 0x7f, 0x5f,
|
||||
0x6e, 0x0c, 0x9a, 0x30, 0x08, 0x7b, 0xea, 0x18, 0x24, 0xda, 0xb0, 0x2b, 0x63, 0x3c, 0xb9, 0x4e,
|
||||
0x66, 0x5d, 0xcf, 0x3a, 0xe7, 0x6a, 0xd7, 0x39, 0x8e, 0xaf, 0x75, 0x9e, 0x8d, 0xbd, 0xdc, 0xa8,
|
||||
0x89, 0x76, 0x75, 0x8c, 0x1a, 0x8d, 0x70, 0x2e, 0xe8, 0xd2, 0xd2, 0x95, 0x6b, 0x0d, 0x97, 0x96,
|
||||
0x5b, 0x5d, 0x1a, 0xcd, 0x15, 0x53, 0x0b, 0x18, 0x19, 0x3a, 0x5b, 0xc7, 0x03, 0xce, 0xd4, 0x95,
|
||||
0xdc, 0x53, 0xb8, 0x13, 0x18, 0xb6, 0x1f, 0xaf, 0x1d, 0x2d, 0xc7, 0xab, 0x63, 0xb1, 0x6f, 0xcf,
|
||||
0xb2, 0x31, 0xdd, 0xd7, 0x8a, 0x76, 0x97, 0xe6, 0x0e, 0xcd, 0x71, 0x8f, 0x76, 0x2a, 0xc1, 0x0c,
|
||||
0x0c, 0x1d, 0x2d, 0xef, 0x6c, 0x01, 0xfe, 0x78, 0x20, 0x48, 0x7c, 0xeb, 0x32, 0xc0, 0xda, 0xa4,
|
||||
0x23, 0xeb, 0x84, 0x86, 0x62, 0x9f, 0x44, 0x33, 0xae, 0xf8, 0x0e, 0x4f, 0x51, 0xab, 0x2e, 0x2d,
|
||||
0x63, 0x9f, 0x01, 0xd8, 0xc4, 0x6a, 0x55, 0x16, 0x4e, 0x22, 0xbd, 0xad, 0xe3, 0x81, 0x67, 0xca,
|
||||
0x67, 0xd1, 0xce, 0x5c, 0x89, 0x48, 0xe1, 0xc1, 0x2e, 0x0d, 0xab, 0x3b, 0x34, 0xa7, 0x9f, 0x9b,
|
||||
0xf1, 0x8c, 0x8d, 0xce, 0xd6, 0x11, 0xd7, 0xc7, 0x25, 0x4d, 0x6f, 0xcc, 0xea, 0xb7, 0x69, 0x8d,
|
||||
0x8b, 0xa3, 0xab, 0x1b, 0x34, 0x7d, 0x7a, 0x03, 0xdf, 0x1f, 0x54, 0x0b, 0x44, 0x44, 0x20, 0x15,
|
||||
0x20, 0xec, 0xd7, 0xb2, 0xb2, 0xff, 0x33, 0xa8, 0x4b, 0xe3, 0xbb, 0xc1, 0x52, 0x4d, 0x7c, 0xdd,
|
||||
0x5a, 0xc6, 0x38, 0x75, 0xd3, 0xc2, 0xfd, 0xdc, 0x6f, 0x1d, 0x1f, 0x7b, 0xa6, 0x7a, 0x5c, 0x7b,
|
||||
0x80, 0x63, 0x13, 0x0a, 0xe2, 0xdb, 0x6d, 0xf2, 0x44, 0x41, 0x91, 0x18, 0x85, 0xae, 0x8a, 0x19,
|
||||
0x36, 0xcd, 0xf6, 0x5d, 0xab, 0xfb, 0x33, 0x67, 0xdb, 0x19, 0x30, 0x2e, 0x7c, 0xe8, 0xac, 0xd5,
|
||||
0xaa, 0xb0, 0xb5, 0x4f, 0xd1, 0xe6, 0x86, 0x5c, 0xc6, 0x7b, 0xe2, 0x92, 0xd6, 0x0c, 0xd5, 0xcb,
|
||||
0x2f, 0x43, 0x7b, 0xf8, 0x64, 0x67, 0x02, 0x67, 0x6a, 0xc2, 0x03, 0x6a, 0x13, 0x83, 0xbb, 0xb5,
|
||||
0x09, 0x11, 0x11, 0x09, 0xa9, 0xfb, 0x33, 0x28, 0xb9, 0xd5, 0xa5, 0x01, 0x37, 0x0c, 0x68, 0x84,
|
||||
0x4d, 0xdb, 0xc1, 0x2b, 0x03, 0x99, 0xef, 0xf6, 0x91, 0x7f, 0xe8, 0xfb, 0x44, 0x9d, 0xa9, 0x3f,
|
||||
0xd6, 0xbf, 0x07, 0xe7, 0x79, 0x51, 0x47, 0xa6, 0xdc, 0x7e, 0xe6, 0x1e, 0xd0, 0x3a, 0xc2, 0x71,
|
||||
0x9c, 0x4b, 0xde, 0xf7, 0x64, 0xd7, 0xd3, 0xc7, 0x05, 0x94, 0x33, 0xef, 0x7b, 0xba, 0x01, 0x3d,
|
||||
0x0e, 0x0d, 0x95, 0x86, 0x6d, 0x30, 0x18, 0xdf, 0x75, 0x1d, 0xd2, 0x71, 0x1c, 0x67, 0x78, 0x60,
|
||||
0xeb, 0x88, 0x26, 0x66, 0x38, 0x8e, 0xf3, 0x56, 0x22, 0x0a, 0x42, 0xb5, 0x75, 0x7c, 0xad, 0x05,
|
||||
0xab, 0x8e, 0xff, 0x0c, 0x33, 0xb2, 0x6c, 0x41, 0xa9, 0xcd, 0xd5, 0x22, 0x13, 0xfa, 0x0d, 0x53,
|
||||
0x70, 0xe4, 0x58, 0x45, 0xcb, 0x00, 0xd2, 0xdb, 0x8f, 0xdc, 0x29, 0xe1, 0xd1, 0x09, 0xd2, 0xdf,
|
||||
0xa1, 0x38, 0x8e, 0xdf, 0x33, 0x30, 0xe7, 0xcf, 0xae, 0x61, 0x45, 0xff, 0x1d, 0x80, 0xf6, 0x04,
|
||||
0xb1, 0x13, 0x8a, 0x76, 0x38, 0x67, 0x90, 0x64, 0xeb, 0xe8, 0xda, 0x16, 0x8e, 0xfd, 0x0c, 0x59,
|
||||
0xb7, 0x2c, 0x6e, 0x10, 0xfa, 0x9a, 0xfa, 0xaf, 0xde, 0xc8, 0xe6, 0x91, 0xfb, 0xa5, 0x1b, 0x25,
|
||||
0x96, 0x08, 0x90, 0x50, 0x42, 0x7b, 0x42, 0xc4, 0x91, 0x09, 0xd3, 0x76, 0x69, 0x87, 0xe3, 0xb8,
|
||||
0x47, 0x33, 0x34, 0x39, 0xe8, 0x96, 0x53, 0xcb, 0x48, 0xa9, 0xbf, 0xec, 0x48, 0x50, 0xea, 0x98,
|
||||
0x10, 0xdb, 0x25, 0x0a, 0xa7, 0x1d, 0xce, 0x69, 0x04, 0xd9, 0x3a, 0xb6, 0xb6, 0x81, 0xfe, 0xcf,
|
||||
0xd0, 0xcf, 0xd0, 0xdf, 0xe4, 0x9c, 0x4c, 0x99, 0x4b, 0x5f, 0xa2, 0xa0, 0x10, 0x26, 0xf8, 0xf6,
|
||||
0x1d, 0x36, 0x94, 0x52, 0xee, 0x74, 0xfc, 0xd5, 0xce, 0x7d, 0x25, 0x35, 0x0c, 0x04, 0x51, 0x14,
|
||||
0x1d, 0xad, 0xf1, 0xae, 0x73, 0xd6, 0xa7, 0x5f, 0x7e, 0x00, 0x23, 0x39, 0x36, 0xd5, 0xcf, 0xf1,
|
||||
0x1e, 0x32, 0xd8, 0x0a, 0x8f, 0xc9, 0x53, 0x65, 0xb5, 0x90, 0xb4, 0xe6, 0xff, 0xb0, 0x5e, 0x3f,
|
||||
0xb9, 0x24, 0x49, 0x92, 0x24, 0x65, 0xb8, 0xf4, 0x26, 0x11, 0xd9, 0x80, 0x37, 0x40, 0x83, 0x95,
|
||||
0x1e, 0x00, 0x0e, 0x9f, 0xf5, 0xff, 0x00, 0xaf, 0xff, 0xde, 0x31, 0x9a, 0x94, 0xc6, 0xcf, 0x20,
|
||||
0x82, 0xce, 0xc1, 0x84, 0x01, 0x1a, 0xac, 0xf4, 0x00, 0xb0, 0xf9, 0xbe, 0x87, 0x01, 0x6e, 0xb3,
|
||||
0x84, 0xa7, 0x1b, 0xa3, 0x31, 0xde, 0x92, 0x34, 0xc7, 0x01, 0x17, 0xfe, 0xcc, 0xa8, 0x30, 0xc0,
|
||||
0xed, 0x78, 0xed, 0x31, 0xd7, 0xb4, 0x25, 0x09, 0xde, 0x66, 0xfc, 0x26, 0xd7, 0xd1, 0x24, 0xec,
|
||||
0xf6, 0x6d, 0xd1, 0x0e, 0x08, 0x17, 0x04, 0xba, 0x4a, 0x5a, 0xfe, 0x52, 0xf3, 0x77, 0x92, 0x17,
|
||||
0xbf, 0x3b, 0xcb, 0x55, 0x9d, 0xe5, 0xaa, 0x6e, 0x09, 0xc5, 0xc3, 0x1c, 0x5b, 0xb4, 0x1c, 0xbd,
|
||||
0x70, 0x3c, 0x66, 0xe1, 0xcf, 0xa9, 0x4b, 0xd9, 0x62, 0xf6, 0x55, 0x8a, 0xed, 0x13, 0xa3, 0x4f,
|
||||
0x65, 0x6e, 0xee, 0xb1, 0x70, 0x04, 0xcb, 0x55, 0x99, 0xe5, 0xea, 0x46, 0x22, 0x70, 0x8c, 0x30,
|
||||
0xb8, 0x53, 0x06, 0xc0, 0x90, 0xe5, 0xea, 0xd3, 0xca, 0x15, 0xd5, 0x94, 0x00, 0x12, 0x41, 0x13,
|
||||
0x88, 0x8c, 0xed, 0x05, 0xbc, 0x70, 0x45, 0x87, 0xe7, 0xaf, 0xce, 0x96, 0xab, 0x10, 0xcb, 0xd5,
|
||||
0xb2, 0x9f, 0x17, 0x30, 0x66, 0x79, 0x1e, 0xe1, 0xcb, 0xdd, 0xc6, 0x46, 0xce, 0x9b, 0xbc, 0xf3,
|
||||
0x89, 0x31, 0x66, 0xd3, 0x7f, 0xd4, 0x72, 0xd5, 0xca, 0x72, 0xf5, 0xba, 0x24, 0x49, 0x92, 0xf4,
|
||||
0x05, 0x52, 0x0d, 0x4e, 0x68, 0xa4, 0x9a, 0xa9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
219
programs/games/dino/trex.c
Normal file
219
programs/games/dino/trex.c
Normal file
@ -0,0 +1,219 @@
|
||||
#include "trex.h"
|
||||
|
||||
Trex trex;
|
||||
|
||||
CollisionBox trexDuckingCollisionBox = {.x = 1, .y = 18, .width = 55, .height = 25};
|
||||
CollisionBox trexRunningCollisionBox[6] =
|
||||
{
|
||||
{.x = 22, .y = 0, .width = 17, .height = 16},
|
||||
{.x = 1, .y = 18, .width = 30, .height = 9},
|
||||
{.x = 10, .y = 35, .width = 14, .height = 8},
|
||||
{.x = 1, .y = 24, .width = 29, .height = 5},
|
||||
{.x = 5, .y = 30, .width = 21, .height = 4},
|
||||
{.x = 9, .y = 34, .width = 15, .height = 4}
|
||||
};
|
||||
|
||||
TrexAnimFramesEntry trexAnimFrames[5] = {
|
||||
{.frameCount = 2, .frames = {44, 0}, .msPerFrame = 1000./3},
|
||||
{.frameCount = 2, .frames = {88, 132}, .msPerFrame = 1000./12},
|
||||
{.frameCount = 1, .frames = {220}, .msPerFrame = 1000./60},
|
||||
{.frameCount = 1, .frames = {0}, .msPerFrame = 1000./60},
|
||||
{.frameCount = 2, .frames = {264, 323}, .msPerFrame = 1000./8}
|
||||
};
|
||||
|
||||
// T - rex player initaliser
|
||||
// Sets the t - rex to blink at random intervals
|
||||
void trexInit() {
|
||||
trex.xPos = 0;
|
||||
trex.currentFrame = 0;
|
||||
//this.currentAnimFrames = [];
|
||||
trex.blinkDelay = 0;
|
||||
trex.blinkCount = 0;
|
||||
trex.animStartTime = 0;
|
||||
trex.timer = 0;
|
||||
trex.msPerFrame = 1000. / FPS;
|
||||
trex.status = TREX_STATUS_WAITING;
|
||||
|
||||
trex.jumping = false;
|
||||
trex.ducking = false;
|
||||
trex.jumpVelocity = 0;
|
||||
trex.reachedMinHeight = false;
|
||||
trex.speedDrop = false;
|
||||
trex.jumpCount = 0;
|
||||
trex.jumpspotX = 0;
|
||||
|
||||
trex.groundYPos = RUNNER_DEFAULT_HEIGHT - TREX_HEIGHT - RUNNER_BOTTOM_PAD;
|
||||
trex.yPos = trex.groundYPos;
|
||||
trex.minJumpHeight = trex.groundYPos - TREX_MIN_JUMP_HEIGHT;
|
||||
trex.playingIntro = false;
|
||||
|
||||
trexDraw(0, 0);
|
||||
trexUpdate(0, TREX_STATUS_WAITING);
|
||||
}
|
||||
|
||||
// Set the animation status
|
||||
void trexUpdate(int deltaTime, int opt_status) {
|
||||
//printf("trex.status = %d\n", trex.status);
|
||||
trex.timer += deltaTime;
|
||||
// Update the status
|
||||
if (opt_status != -1) {
|
||||
trex.status = opt_status;
|
||||
trex.currentFrame = 0;
|
||||
trex.msPerFrame = trexAnimFrames[opt_status].msPerFrame;
|
||||
trex.currentAnimFrames = trexAnimFrames[opt_status];
|
||||
if (opt_status == TREX_STATUS_WAITING) {
|
||||
trex.animStartTime = getTimeStamp();
|
||||
trexSetBlinkDelay();
|
||||
}
|
||||
}
|
||||
// Game intro animation, T-rex moves in from the left.
|
||||
if (trex.playingIntro) {
|
||||
if (trex.xPos < TREX_START_X_POS) {
|
||||
//printf("trex.xPos = %d\n", trex.xPos);
|
||||
trex.xPos += max((int)round(((double)TREX_START_X_POS / TREX_INTRO_DURATION) * deltaTime), 1);
|
||||
}
|
||||
else {
|
||||
runnerStartGame();
|
||||
}
|
||||
}
|
||||
|
||||
if (trex.status == TREX_STATUS_WAITING) {
|
||||
trexBlink(getTimeStamp());
|
||||
}
|
||||
else {
|
||||
// printf("trex.status = %d\n", trex.status);
|
||||
trexDraw(trex.currentAnimFrames.frames[trex.currentFrame], 0);
|
||||
}
|
||||
|
||||
// Update the frame position.
|
||||
if (trex.timer >= trex.msPerFrame) {
|
||||
trex.currentFrame = trex.currentFrame == trex.currentAnimFrames.frameCount - 1 ? 0 : trex.currentFrame + 1;
|
||||
trex.timer = 0;
|
||||
}
|
||||
|
||||
// Speed drop becomes duck if the down key is still being pressed.
|
||||
if (trex.speedDrop && trex.yPos == trex.groundYPos) {
|
||||
trex.speedDrop = false;
|
||||
trexSetDuck(true);
|
||||
}
|
||||
}
|
||||
|
||||
void trexDraw(int x, int y) {
|
||||
//printf("trexDraw();\n");
|
||||
int sourceWidth = trex.ducking && trex.status != TREX_STATUS_CRASHED ? TREX_WIDTH_DUCK : TREX_WIDTH;
|
||||
int sourceHeight = TREX_HEIGHT;
|
||||
// Adjustments for sprite sheet position.
|
||||
int sourceX = x + ATLAS_TREX_X;
|
||||
int sourceY = y + ATLAS_TREX_Y;
|
||||
|
||||
// Ducking.
|
||||
if (trex.ducking && trex.status != TREX_STATUS_CRASHED) {
|
||||
graphicsBlitAtlasImage(sourceX, sourceY, trex.xPos, trex.yPos, sourceWidth, sourceHeight, false);
|
||||
}
|
||||
else {
|
||||
// Crashed whilst ducking. Trex is standing up so needs adjustment.
|
||||
if (trex.ducking && trex.status == TREX_STATUS_CRASHED) {
|
||||
trex.xPos++;
|
||||
}
|
||||
// Standing / running
|
||||
graphicsBlitAtlasImage(sourceX, sourceY, trex.xPos, trex.yPos, sourceWidth, sourceHeight, false);
|
||||
}
|
||||
}
|
||||
|
||||
void trexSetBlinkDelay() {
|
||||
trex.blinkDelay = (int)ceil(((double)rand()/RAND_MAX)*TREX_BLINK_TIMING);
|
||||
}
|
||||
|
||||
void trexBlink(int time) {
|
||||
//printf("trexBlink(%d)\n", time);
|
||||
int deltaTime = time - trex.animStartTime;
|
||||
if (deltaTime < 0) {
|
||||
deltaTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
if (deltaTime >= trex.blinkDelay) {
|
||||
trexDraw(trex.currentAnimFrames.frames[trex.currentFrame], 0);
|
||||
if (trex.currentFrame == 1) {
|
||||
// Set new random delay to blink.
|
||||
trexSetBlinkDelay();
|
||||
trex.animStartTime = time;
|
||||
trex.blinkCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise a jump
|
||||
void trexStartJump(double speed) {
|
||||
if (!trex.jumping) {
|
||||
trexUpdate(0, TREX_STATUS_JUMPING);
|
||||
// Tweak the jump velocity based on the speed
|
||||
trex.jumpVelocity = TREX_INITIAL_JUMP_VELOCITY - (speed / 10);
|
||||
trex.jumping = true;
|
||||
trex.reachedMinHeight = false;
|
||||
trex.speedDrop = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Jump is complete, falling down
|
||||
void trexEndJump() {
|
||||
if (trex.reachedMinHeight && trex.jumpVelocity < TREX_DROP_VELOCITY) {
|
||||
trex.jumpVelocity = TREX_DROP_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
// Update frame for a jump
|
||||
void trexUpdateJump(int deltaTime) {
|
||||
double msPerFrame = trexAnimFrames[trex.status].msPerFrame;
|
||||
double framesElapsed = deltaTime / msPerFrame;
|
||||
|
||||
// Speed drop makes Trex fall faster.
|
||||
if (trex.speedDrop) {
|
||||
trex.yPos += (int)round(trex.jumpVelocity * TREX_SPEED_DROP_COEFFICIENT * framesElapsed);
|
||||
}
|
||||
else {
|
||||
trex.yPos += (int)round(trex.jumpVelocity * framesElapsed);
|
||||
}
|
||||
trex.jumpVelocity += TREX_GRAVITY * framesElapsed;
|
||||
// Minimum height has been reached.
|
||||
if (trex.yPos < trex.minJumpHeight || trex.speedDrop) {
|
||||
trex.reachedMinHeight = true;
|
||||
}
|
||||
// Reached max height
|
||||
if (trex.yPos < TREX_MAX_JUMP_HEIGHT || trex.speedDrop) {
|
||||
trexEndJump();
|
||||
}
|
||||
// Back down at ground level. Jump completed.
|
||||
if (trex.yPos > trex.groundYPos) {
|
||||
trexReset();
|
||||
trex.jumpCount++;
|
||||
}
|
||||
trexUpdate(deltaTime, -1);
|
||||
}
|
||||
|
||||
// Set the speed drop.Immediately cancels the current jump
|
||||
void trexSetSpeedDrop() {
|
||||
trex.speedDrop = true;
|
||||
trex.jumpVelocity = 1;
|
||||
}
|
||||
|
||||
void trexSetDuck(bool isDucking) {
|
||||
if (isDucking && trex.status != TREX_STATUS_DUCKING) {
|
||||
trexUpdate(0, TREX_STATUS_DUCKING);
|
||||
trex.ducking = true;
|
||||
}
|
||||
else if (trex.status == TREX_STATUS_DUCKING) {
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
trex.ducking = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the t-rex to running at start of game
|
||||
void trexReset() {
|
||||
trex.yPos = trex.groundYPos;
|
||||
trex.jumpVelocity = 0;
|
||||
trex.jumping = false;
|
||||
trex.ducking = false;
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
//trex.midair = false; TODO: WTF is midair
|
||||
trex.speedDrop = false;
|
||||
trex.jumpCount = 0;
|
||||
}
|
83
programs/games/dino/trex.h
Normal file
83
programs/games/dino/trex.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef TREX_H
|
||||
#define TREX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "collisionbox.h"
|
||||
#include "runner.h"
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
// Blinking coefficient
|
||||
#define TREX_BLINK_TIMING 7000
|
||||
|
||||
#define TREX_DROP_VELOCITY -5
|
||||
#define TREX_GRAVITY 0.6
|
||||
#define TREX_HEIGHT 47
|
||||
#define TREX_HEIGHT_DUCK 25
|
||||
#define TREX_INITIAL_JUMP_VELOCITY -10
|
||||
#define TREX_INTRO_DURATION 750
|
||||
#define TREX_MAX_JUMP_HEIGHT 30
|
||||
#define TREX_MIN_JUMP_HEIGHT 30
|
||||
#define TREX_SPEED_DROP_COEFFICIENT 3
|
||||
#define TREX_SPRITE_WIDTH 262
|
||||
#define TREX_START_X_POS 25
|
||||
#define TREX_WIDTH 44
|
||||
#define TREX_WIDTH_DUCK 59
|
||||
|
||||
// Animation states
|
||||
typedef enum {
|
||||
TREX_STATUS_WAITING = 0,
|
||||
TREX_STATUS_RUNNING = 1,
|
||||
TREX_STATUS_CRASHED = 2,
|
||||
TREX_STATUS_JUMPING = 3,
|
||||
TREX_STATUS_DUCKING = 4,
|
||||
} TrexStatus;
|
||||
|
||||
typedef struct {
|
||||
int frameCount;
|
||||
int frames[2];
|
||||
double msPerFrame;
|
||||
} TrexAnimFramesEntry;
|
||||
|
||||
typedef struct {
|
||||
int xPos;
|
||||
int yPos;
|
||||
int groundYPos;
|
||||
int currentFrame;
|
||||
TrexAnimFramesEntry currentAnimFrames;
|
||||
int blinkDelay;
|
||||
int blinkCount;
|
||||
int animStartTime;
|
||||
int timer;
|
||||
double msPerFrame;
|
||||
TrexStatus status;
|
||||
bool jumping;
|
||||
bool ducking;
|
||||
double jumpVelocity;
|
||||
bool reachedMinHeight;
|
||||
bool speedDrop;
|
||||
int jumpCount;
|
||||
int jumpspotX;
|
||||
int minJumpHeight;
|
||||
bool playingIntro;
|
||||
} Trex;
|
||||
|
||||
extern CollisionBox trexDuckingCollisionBox;
|
||||
extern CollisionBox trexRunningCollisionBox[6];
|
||||
extern Trex trex;
|
||||
|
||||
void trexInit();
|
||||
void trexUpdate(int deltaTime, int opt_status);
|
||||
void trexDraw(int x, int y);
|
||||
void trexSetBlinkDelay();
|
||||
void trexBlink(int time);
|
||||
void trexStartJump(double speed);
|
||||
void trexEndJump();
|
||||
void trexUpdateJump(int deltaTime);
|
||||
void trexSetSpeedDrop();
|
||||
void trexSetDuck(bool isDucking);
|
||||
void trexReset();
|
||||
|
||||
#endif
|
241
programs/games/dino/ulist.c
Normal file
241
programs/games/dino/ulist.c
Normal file
@ -0,0 +1,241 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ulist.h"
|
||||
|
||||
Ulist* ulist_create() {
|
||||
Ulist* list = (Ulist*)malloc(sizeof(Ulist));
|
||||
if (list == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->size = 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
void ulist_destroy(Ulist* list) {
|
||||
Node* current = list->head;
|
||||
Node* next;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
void ulist_push_front(Ulist* list, void* data) {
|
||||
Node* new_node = (Node*)malloc(sizeof(Node));
|
||||
if (new_node == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
new_node->data = data;
|
||||
new_node->prev = NULL;
|
||||
new_node->next = list->head;
|
||||
|
||||
if (list->head != NULL) {
|
||||
list->head->prev = new_node;
|
||||
}
|
||||
|
||||
list->head = new_node;
|
||||
|
||||
if (list->tail == NULL) {
|
||||
list->tail = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void ulist_push_back(Ulist* list, void* data) {
|
||||
Node* new_node = (Node*)malloc(sizeof(Node));
|
||||
if (new_node == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
new_node->data = data;
|
||||
new_node->next = NULL;
|
||||
new_node->prev = list->tail;
|
||||
|
||||
if (list->tail != NULL) {
|
||||
list->tail->next = new_node;
|
||||
}
|
||||
|
||||
list->tail = new_node;
|
||||
|
||||
if (list->head == NULL) {
|
||||
list->head = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void ulist_remove(Ulist* list, Node* node) {
|
||||
if (list == NULL || node == NULL) {
|
||||
return;
|
||||
}
|
||||
// Update previous node's next pointer
|
||||
if (node->prev != NULL) {
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
else {
|
||||
// If the node is the head, update the head pointer
|
||||
list->head = node->next;
|
||||
}
|
||||
// Update next node's previous pointer
|
||||
if (node->next != NULL) {
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
else {
|
||||
// If the node is the tail, update the tail pointer
|
||||
list->tail = node->prev;
|
||||
}
|
||||
// Free the memory occupied by the node
|
||||
free(node);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
void ulist_remove_front(Ulist* list) {
|
||||
if (list->head == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* node_to_remove = list->head;
|
||||
list->head = list->head->next;
|
||||
|
||||
if (list->head != NULL) {
|
||||
list->head->prev = NULL;
|
||||
}
|
||||
else {
|
||||
list->tail = NULL;
|
||||
}
|
||||
|
||||
free(node_to_remove);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
void ulist_splice(Ulist* list, int n) {
|
||||
if (list->size <= n) {
|
||||
return; // No need to splice if the list size is less than or equal to n
|
||||
}
|
||||
int count = list->size - n;
|
||||
while (count > 0) {
|
||||
ulist_remove_back(list);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void ulist_remove_back(Ulist* list) {
|
||||
if (list->tail == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* node_to_remove = list->tail;
|
||||
list->tail = list->tail->prev;
|
||||
|
||||
if (list->tail != NULL) {
|
||||
list->tail->next = NULL;
|
||||
}
|
||||
else {
|
||||
list->head = NULL;
|
||||
}
|
||||
|
||||
free(node_to_remove);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
int ulist_search(Ulist* list, void* data) {
|
||||
Node* current = list->head;
|
||||
int index = 0;
|
||||
|
||||
while (current != NULL) {
|
||||
if (current->data == data) {
|
||||
return index;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* ulist_get_front(Ulist* list) {
|
||||
if (list->head == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->head->data;
|
||||
}
|
||||
|
||||
void* ulist_get_back(Ulist* list) {
|
||||
if (list->tail == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->tail->data;
|
||||
}
|
||||
|
||||
int ulist_size(Ulist* list) {
|
||||
return list->size;
|
||||
}
|
||||
|
||||
void ulist_print(Ulist* list) {
|
||||
Node* current = list->head;
|
||||
|
||||
while (current != NULL) {
|
||||
printf("%p ", current->data);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void ulist_test() {
|
||||
// Create a new Ulist
|
||||
Ulist* list = ulist_create();
|
||||
|
||||
// Test insertFront
|
||||
int data1 = 10;
|
||||
ulist_push_front(list, &data1);
|
||||
printf("List after inserting 10 at the front: ");
|
||||
ulist_print(list); // Expected output: 10
|
||||
|
||||
// Test insertBack
|
||||
int data2 = 20;
|
||||
ulist_push_back(list, &data2);
|
||||
printf("List after inserting 20 at the back: ");
|
||||
ulist_print(list); // Expected output: 10 20
|
||||
|
||||
// Test removeFront
|
||||
ulist_remove_front(list);
|
||||
printf("List after removing front element: ");
|
||||
ulist_print(list); // Expected output: 20
|
||||
|
||||
// Test removeBack
|
||||
ulist_remove_back(list);
|
||||
printf("List after removing back element: ");
|
||||
ulist_print(list); // Expected output:
|
||||
|
||||
// Test search
|
||||
int data3 = 30;
|
||||
ulist_push_front(list, &data3);
|
||||
printf("Index of 30 in the list: %d\n", ulist_search(list, &data3)); // Expected output: 0
|
||||
|
||||
// Test getFront
|
||||
int* front = (int*)ulist_get_front(list);
|
||||
printf("Front element of the list: %d\n", *front); // Expected output: 30
|
||||
|
||||
// Test getBack
|
||||
int* back = (int*)ulist_get_back(list);
|
||||
printf("Back element of the list: %d\n", *back); // Expected output: 30
|
||||
|
||||
// Test getSize
|
||||
printf("Size of the list: %d\n", ulist_size(list)); // Expected output: 1
|
||||
|
||||
// Destroy the list
|
||||
ulist_destroy(list);
|
||||
}
|
31
programs/games/dino/ulist.h
Normal file
31
programs/games/dino/ulist.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef ULIST_H_
|
||||
#define ULIST_H_
|
||||
|
||||
typedef struct Node {
|
||||
void* data;
|
||||
struct Node* prev;
|
||||
struct Node* next;
|
||||
} Node;
|
||||
|
||||
typedef struct Ulist {
|
||||
Node* head;
|
||||
Node* tail;
|
||||
int size;
|
||||
} Ulist;
|
||||
|
||||
Ulist* ulist_create();
|
||||
void ulist_destroy(Ulist* list);
|
||||
void ulist_push_front(Ulist* list, void* data);
|
||||
void ulist_push_back(Ulist* list, void* data);
|
||||
void ulist_remove(Ulist *list, Node *node);
|
||||
void ulist_remove_front(Ulist* list);
|
||||
void ulist_splice(Ulist* list, int n);
|
||||
void ulist_remove_back(Ulist* list);
|
||||
int ulist_search(Ulist* list, void* data);
|
||||
void* ulist_get_front(Ulist* list);
|
||||
void* ulist_get_back(Ulist* list);
|
||||
int ulist_size(Ulist* list);
|
||||
void ulist_print(Ulist* list);
|
||||
void ulist_test();
|
||||
|
||||
#endif /* ULIST_H_ */
|
Loading…
x
Reference in New Issue
Block a user