poorly coded platformer in c++
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

326 lines
8.3 KiB

#include <iostream>
#include <fstream>
#include <vector>
#include <SDL.h>
#include <SDL_image.h>
// 16*16 tiles
#define RENDER_WIDTH 256
// 16*11 tiles
#define RENDER_HEIGHT 176
#define WINDOW_WIDTH RENDER_WIDTH*4
#define WINDOW_HEIGHT RENDER_HEIGHT*4
#define WINDOW_TITLE "game"
#define GFX_PATH "gfx/"
#define LEVELS_FOLDER "lvls/"
#define MAX_MAP_TILES_X 16 /*11*/
#define MAX_MAP_TILES_Y 11 /*16*/
#define TILE_WIDTH 16
#define TILE_HEIGHT 16
#define PLAYER_SPEED 1.0f
#define UNUSED(x) (void)(x)
//#define for_map for (int col = 0; col < MAX_MAP_TILES_Y; ++col) for (int row = 0; row < MAX_MAP_TILES_X; ++row)
#define debug_print_rect(r) printf("x: %d, y: %d, w: %d, h: %d\n", r.x, r.y, r.w, r.h);
#define USE_VSYNC 0
#define USE_LOGICAL_RENDER_VIEW 1
#define FPS 60
//#define USE_STATIC_ARRAY_LVL
using namespace std;
// Types
struct Rect {
SDL_Rect rect;
Rect() { rect = {}; }
Rect(int x, int y, int w, int h) {
rect.x = x; rect.y = y;
rect.w = w; rect.h = h;
}
Rect(Rect& r) {
rect.x = r.rect.x;
rect.y = r.rect.y;
rect.w = r.rect.w;
rect.h = r.rect.h;
}
bool operator ==(Rect& r) {
auto s = r.rect;
return (s.x == rect.x &&
s.y == rect.y &&
s.w == rect.w &&
s.h == rect.h);
}
bool operator !=(Rect& r) {
auto s = r.rect;
return (s.x != rect.x ||
s.y != rect.y ||
s.w != rect.w ||
s.h != rect.h);
}
void operator =(Rect& r) {
rect.x = r.rect.x;
rect.y = r.rect.y;
rect.w = r.rect.w;
rect.h = r.rect.h;
}
SDL_Rect* operator ()(){
return &rect;
}
void print() {
auto r = rect;
printf("x: %d, y: %d, w: %d, h: %d\n", r.x, r.y, r.w, r.h);
}
};
//typedef int Room[MAX_MAP_TILES_X][MAX_MAP_TILES_Y];
typedef int Room[MAX_MAP_TILES_Y][MAX_MAP_TILES_X];
struct R {
Room room;
int operator ()(int x, int y) {
return room[x][y];
}
};
/*struct Keys {
static bool down_pressed;
static bool up_pressed;
static bool left_pressed;
static bool right_pressed;
};
bool Keys::down_pressed = false;
bool Keys::up_pressed = false;
bool Keys::left_pressed = false;
bool Keys::right_pressed = false;
*/
// Global variables
vector<R> rooms;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* tiles;
bool quit;
struct Player {
Rect src_rect;
Rect body_hitbox; // player is a 16*16 tile + 8 pixels in height for the head, we ignore those
int x, y;
float speed;
int x_vel, y_vel;
Player() : src_rect(0, 39, TILE_WIDTH, TILE_HEIGHT + 10/*head size*/), body_hitbox(0, 48, TILE_WIDTH, TILE_HEIGHT), x(0), y(0), speed(PLAYER_SPEED)
,x_vel(0), y_vel(0) {}
void draw() {
Rect dst(x, y, src_rect()->w, src_rect()->h);
SDL_RenderCopy(renderer, tiles, src_rect(), dst());
}
void update() {
// TODO: time wtf, tick
/*if (Keys::down_pressed) y += speed;
if (Keys::up_pressed) y -= speed;
if (Keys::left_pressed) x -= speed;
if (Keys::right_pressed) x += speed;*/
x += x_vel;
y += y_vel;
}
} player;
// A room is a screen in the sense of a static screen, aka the player doesnt move a camera,
// he just moves in the current room
/*
#ifndef USE_STATIC_ARRAY_LVL
int room[MAX_MAP_TILES_X][MAX_MAP_TILES_Y];
#else
int room[MAX_MAP_TILES_Y][MAX_MAP_TILES_X] = {
{001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 001, 000, 001, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 001, 000, 001, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 001, 001, 001, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001},
{001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001}
};
#endif
*/
Rect test_tile(0, 0, 16, 16);
Rect dest_test_tile(0, 0, 16, 16);
Rect stone_tile(0, 17, 16, 16);
// Prototypes
void die(const string& why);
void endgame();
bool loadgraphics();
bool load_room(const string& name);
void drawtile(Rect src, int x, int y);
void draw_room(int* room_num);
extern "C" int main(int argc, char** argv) {
UNUSED(argc);
UNUSED(argv);
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, 0);
if (!window) die("failed to create window");
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED
#if USE_VSYNC
| SDL_RENDERER_PRESENTVSYNC);
#else
);
#endif
if (!renderer) die("failed to create renderer");
#if USE_LOGICAL_RENDER_VIEW
SDL_RenderSetLogicalSize(renderer, RENDER_WIDTH, RENDER_HEIGHT);
#endif
if (!loadgraphics()) die("failed to load tiles.png");
#ifndef USE_STATIC_ARRAY_LVL
if (!load_room("00")) die("Failed to load level 00");
if (!load_room("01")) die("Failed to load level 01");
#endif
SDL_SetRenderDrawColor(renderer, 0, 255, 150, 255);
int next_room(0);
quit = false;
//float now(0), secs(0), last_time(0);
while (!quit) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) quit = true;
if (e.type == SDL_KEYDOWN) {
switch (e.key.keysym.sym) {
case SDLK_ESCAPE: quit = true; break;
// Debug
case SDLK_0: next_room = 0; break;
case SDLK_1: next_room = 1; break;
case SDLK_2: next_room = 2; break;
// fin debug
case SDLK_DOWN: player.y_vel = PLAYER_SPEED; break;
case SDLK_UP: player.y_vel = -PLAYER_SPEED; break;
case SDLK_RIGHT: player.x_vel = PLAYER_SPEED; break;
case SDLK_LEFT: player.x_vel = -PLAYER_SPEED; break;
}
} else if (e.type == SDL_KEYUP) {
switch (e.key.keysym.sym) {
case SDLK_DOWN: if (player.y_vel > 0) player.y_vel = 0; break;
case SDLK_UP: if (player.y_vel < 0) player.y_vel = 0; break;
case SDLK_RIGHT: if (player.x_vel > 0) player.x_vel = 0; break;
case SDLK_LEFT: if (player.x_vel < 0) player.x_vel = 0; break;
}
}
}
player.update(); //TODO: time and shit
SDL_RenderClear(renderer);
// Current room rendering
draw_room(&next_room);
player.draw();
/*
float freq = SDL_GetPerformanceFrequency();
now = SDL_GetPerformanceCounter();
secs = (now - last_time) / freq;
SDL_Delay(FPS - secs * 1000);
*/
SDL_Delay(16);
SDL_RenderPresent(renderer);
}
/*whats your*/endgame();
return 0;
}
void draw_room(int* room_num) {
try {
(void)rooms.at((unsigned)*room_num);
} catch (const out_of_range& ex) {
cerr << "out_of_range exception caught in draw_room routine: map nb " << *room_num << " doesnt exist or hasnt been loaded. Reseting to map nb 00." << endl;
*room_num = 0; // reset room number
return;
}
for (int y = 0; y < MAX_MAP_TILES_Y; ++y) {
for (int x = 0; x < MAX_MAP_TILES_X; ++x) {
int tile = rooms[(unsigned)*room_num](y, x);
Rect defr(17, 0, 16, 16);
Rect r = defr;
switch (tile) {
case 000: r = test_tile; break;
case 002: r = stone_tile; break;
default: r = defr; break;
}
drawtile(r, x * TILE_WIDTH, y * TILE_HEIGHT);
}
}
}
void die(const string& why) {
cerr << why << endl;
exit(-1);
}
void endgame() {
if (tiles) free(tiles);
if (renderer) SDL_DestroyRenderer(renderer);
if (window) SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
bool loadgraphics() {
tiles = IMG_LoadTexture(renderer, GFX_PATH "tiles.png");
if (!tiles) cerr << SDL_GetError() << endl;
return (tiles) ? true : false;
}
bool load_room(const string& name) {
// TODO: charger les maps dans une hashtable <UniqueConstID, map> ? le vector peut sort() etc, pas safe?
cout << "loading level " << name << endl;
ifstream file(LEVELS_FOLDER + name + ".lvl");
if (!file.is_open()) return false;
R room;
for (int y = 0; y < MAX_MAP_TILES_Y; ++y) {
for (int x = 0; x < MAX_MAP_TILES_X; ++x) {
//file >> room[y][x];
file >> room.room[y][x];
}
}
rooms.push_back(room);
return true;
}
void drawtile(Rect src, int x, int y) {
Rect r(x, y, TILE_WIDTH, TILE_HEIGHT);
SDL_RenderCopy(renderer, tiles, &src.rect, &r.rect);
}