best game of 2022
This commit is contained in:
parent
2e513649e0
commit
553678b169
5 changed files with 257 additions and 51 deletions
BIN
assets/fish/angryfish.png
Normal file
BIN
assets/fish/angryfish.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.3 KiB |
BIN
assets/fish/fish.png
Normal file
BIN
assets/fish/fish.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
|
@ -1,9 +1,10 @@
|
||||||
project('rotcpu', 'cpp')
|
project('fish-simulator', 'c')
|
||||||
|
|
||||||
sdl2_dep = dependency('sdl2')
|
sdl2_dep = dependency('sdl2')
|
||||||
|
sdl2_image_dep = dependency('sdl2_image')
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'rotcpuemu',
|
'fish-simulator',
|
||||||
'./src/main.cpp',
|
'./src/main.c',
|
||||||
dependencies : [sdl2_dep]
|
dependencies : [sdl2_dep, sdl2_image_dep]
|
||||||
)
|
)
|
||||||
|
|
252
src/main.c
Normal file
252
src/main.c
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "SDL_events.h"
|
||||||
|
#include "SDL_rect.h"
|
||||||
|
#include "SDL_render.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_timer.h"
|
||||||
|
#include "SDL_video.h"
|
||||||
|
|
||||||
|
#define FISHES_MAX 1024
|
||||||
|
#define SIMULATION_DELTA_TIME (1.0f / 60.0f)
|
||||||
|
|
||||||
|
enum fish_type {
|
||||||
|
FISH_TYPE_NORMAL,
|
||||||
|
FISH_TYPE_ANGRY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fish_state {
|
||||||
|
FISH_STATE_NONE,
|
||||||
|
FISH_STATE_INIT,
|
||||||
|
FISH_STATE_WANDER_PICK_POINT,
|
||||||
|
FISH_STATE_WANDER_TRANSITION,
|
||||||
|
FISH_STATE_WANDER_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fish {
|
||||||
|
int x, y, w, h;
|
||||||
|
enum fish_type type;
|
||||||
|
enum fish_state state;
|
||||||
|
|
||||||
|
/* state arguments */
|
||||||
|
float wander_start_x, wander_start_y, wander_target_x, wander_target_y, wander_step; /* FISH_STATE_WANDER_* */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct app {
|
||||||
|
struct fish *fishes[FISHES_MAX];
|
||||||
|
int fishes_count;
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
|
||||||
|
SDL_Texture *fish_texture;
|
||||||
|
SDL_Texture *angry_fish_texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
float lerp(float a, float b, float t)
|
||||||
|
{
|
||||||
|
return a + (b - a) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc(int code)
|
||||||
|
{
|
||||||
|
if (code < 0) {
|
||||||
|
fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *scp(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) {
|
||||||
|
fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fishes_add(struct app *app, int x, int y, int w, int h, enum fish_type type)
|
||||||
|
{
|
||||||
|
struct fish *new_fish = malloc(sizeof(struct fish));
|
||||||
|
new_fish->x = x;
|
||||||
|
new_fish->y = y;
|
||||||
|
new_fish->w = w;
|
||||||
|
new_fish->h = h;
|
||||||
|
new_fish->type = type;
|
||||||
|
new_fish->state = FISH_STATE_INIT;
|
||||||
|
|
||||||
|
for (int i = 0; i < FISHES_MAX; i++) {
|
||||||
|
if (app->fishes[i] == NULL) {
|
||||||
|
app->fishes[i] = new_fish;
|
||||||
|
app->fishes_count++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fish_update(const struct app *app, struct fish *fish, float delta_time)
|
||||||
|
{
|
||||||
|
switch (fish->state)
|
||||||
|
{
|
||||||
|
case FISH_STATE_INIT: {
|
||||||
|
fish->state = FISH_STATE_WANDER_PICK_POINT;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FISH_STATE_WANDER_PICK_POINT: {
|
||||||
|
int width, height;
|
||||||
|
SDL_GetWindowSize(app->window, &width, &height);
|
||||||
|
|
||||||
|
fish->wander_target_x = rand() % width;
|
||||||
|
fish->wander_target_y = rand() % height;
|
||||||
|
fish->wander_start_x = fish->x;
|
||||||
|
fish->wander_start_y = fish->y;
|
||||||
|
fish->wander_step = 0.1;
|
||||||
|
fish->state = FISH_STATE_WANDER_TRANSITION;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FISH_STATE_WANDER_TRANSITION: {
|
||||||
|
if (fish->x != fish->wander_target_x) {
|
||||||
|
fish->x = lerp(fish->wander_start_x, fish->wander_target_x, fish->wander_step);
|
||||||
|
}
|
||||||
|
if (fish->y != fish->wander_target_y) {
|
||||||
|
fish->y = lerp(fish->wander_start_y, fish->wander_target_y, fish->wander_step);
|
||||||
|
}
|
||||||
|
if (fish->wander_step >= 1.0) {
|
||||||
|
fish->state = FISH_STATE_WANDER_DONE;
|
||||||
|
}
|
||||||
|
fish->wander_step += 0.05 * delta_time;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FISH_STATE_WANDER_DONE: {
|
||||||
|
fish->state = FISH_STATE_INIT;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FISH_STATE_NONE: /* through */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fish_draw(const struct app *app, const struct fish *fish)
|
||||||
|
{
|
||||||
|
SDL_Rect rect = {
|
||||||
|
.x = fish->x,
|
||||||
|
.y = fish->y,
|
||||||
|
.w = fish->w,
|
||||||
|
.h = fish->h
|
||||||
|
};
|
||||||
|
SDL_Texture *texture = fish->type == FISH_TYPE_ANGRY ? app->angry_fish_texture : app->fish_texture;
|
||||||
|
SDL_RenderCopy(app->renderer, texture, NULL, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct app *app_new()
|
||||||
|
{
|
||||||
|
struct app *app = malloc(sizeof(struct app));
|
||||||
|
|
||||||
|
scc(SDL_Init(SDL_INIT_VIDEO));
|
||||||
|
scc(SDL_CreateWindowAndRenderer(320, 240, SDL_WINDOW_RESIZABLE, &app->window, &app->renderer));
|
||||||
|
app->fish_texture = scp(IMG_LoadTexture(app->renderer, "./assets/fish/fish.png"));
|
||||||
|
app->angry_fish_texture = scp(IMG_LoadTexture(app->renderer, "./assets/fish/angryfish.png"));
|
||||||
|
fishes_add(app, 20, 20, 128, 128, FISH_TYPE_NORMAL);
|
||||||
|
fishes_add(app, 20, 150, 128, 128, FISH_TYPE_NORMAL);
|
||||||
|
fishes_add(app, 150, 150, 128, 128, FISH_TYPE_ANGRY);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_update(struct app *app, float delta_time)
|
||||||
|
{
|
||||||
|
/* fishes */
|
||||||
|
{
|
||||||
|
int found_fishes = 0;
|
||||||
|
for (int i = 0; i < FISHES_MAX; i++) {
|
||||||
|
if (app->fishes[i] != NULL) {
|
||||||
|
found_fishes++;
|
||||||
|
fish_update(app, app->fishes[i], delta_time);
|
||||||
|
}
|
||||||
|
if (found_fishes >= app->fishes_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_draw(struct app *app)
|
||||||
|
{
|
||||||
|
/* background */
|
||||||
|
{
|
||||||
|
SDL_SetRenderDrawColor(app->renderer, 0x11, 0x65, 0xBA, 0xff);
|
||||||
|
SDL_RenderClear(app->renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fishes */
|
||||||
|
{
|
||||||
|
int found_fishes = 0;
|
||||||
|
for (int i = 0; i < FISHES_MAX; i++) {
|
||||||
|
if (app->fishes[i] != NULL) {
|
||||||
|
found_fishes++;
|
||||||
|
fish_draw(app, app->fishes[i]);
|
||||||
|
}
|
||||||
|
if (found_fishes >= app->fishes_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_loop(struct app *app) {
|
||||||
|
SDL_Event event;
|
||||||
|
Uint32 prev_ticks = SDL_GetTicks();
|
||||||
|
float lag_sec = 0;
|
||||||
|
while (1) {
|
||||||
|
Uint32 current_ticks = SDL_GetTicks();
|
||||||
|
lag_sec += (float) (current_ticks - prev_ticks) / 1000.0f;
|
||||||
|
SDL_PollEvent(&event);
|
||||||
|
if (event.type == SDL_QUIT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SDL_Delay(1);
|
||||||
|
while (lag_sec >= SIMULATION_DELTA_TIME) {
|
||||||
|
app_update(app, SIMULATION_DELTA_TIME);
|
||||||
|
lag_sec -= SIMULATION_DELTA_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app_draw(app);
|
||||||
|
|
||||||
|
SDL_RenderPresent(app->renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_free(struct app *app)
|
||||||
|
{
|
||||||
|
int found_fishes = 0;
|
||||||
|
for (int i = 0; i < FISHES_MAX; i++) {
|
||||||
|
if (app->fishes[i] != NULL) {
|
||||||
|
free(app->fishes[i]);
|
||||||
|
found_fishes++;
|
||||||
|
}
|
||||||
|
if (found_fishes >= app->fishes_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_DestroyRenderer(app->renderer);
|
||||||
|
SDL_DestroyWindow(app->window);
|
||||||
|
SDL_DestroyTexture(app->fish_texture);
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct app *app = app_new();
|
||||||
|
app_loop(app);
|
||||||
|
app_free(app);
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
47
src/main.cpp
47
src/main.cpp
|
@ -1,47 +0,0 @@
|
||||||
#include "SDL.h"
|
|
||||||
|
|
||||||
void scc(int code)
|
|
||||||
{
|
|
||||||
if (code < 0) {
|
|
||||||
fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *scp(void *ptr)
|
|
||||||
{
|
|
||||||
if (ptr == NULL) {
|
|
||||||
fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
SDL_Window *window;
|
|
||||||
SDL_Renderer *renderer;
|
|
||||||
SDL_Surface *surface;
|
|
||||||
SDL_Event event;
|
|
||||||
|
|
||||||
scc(SDL_Init(SDL_INIT_VIDEO));
|
|
||||||
scc(SDL_CreateWindowAndRenderer(320, 240, SDL_WINDOW_RESIZABLE, &window, &renderer));
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
SDL_PollEvent(&event);
|
|
||||||
if (event.type == SDL_QUIT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_DestroyRenderer(renderer);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in a new issue