Added space background

This commit is contained in:
2025-12-31 18:50:45 +08:00
parent 90d76b585c
commit 888b0c368c
10 changed files with 301 additions and 177 deletions

11
.gitignore vendored
View File

@ -1 +1,12 @@
build/ build/
.vscode/
*.o
*.exe
*.out
*.log
.DS_Store
star-invaders
*.kra
*.xcf
*.png

View File

@ -1,16 +0,0 @@
cmake_minimum_required(VERSION 3.10)
project(SDL2_Example LANGUAGES C)
# Set the C standard to C99
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Find SDL2
find_package(SDL2 REQUIRED)
# Add your executable target
file(GLOB SOURCES "src/*.c")
add_executable(star-invaders ${SOURCES})
# Link the SDL2 libraries to your executable
target_link_libraries(star-invaders PRIVATE SDL2::SDL2)

29
Makefile Normal file
View File

@ -0,0 +1,29 @@
# Simple Makefile using sdl-config for SDL flags
CC := gcc
SDL_CFLAGS := $(shell sdl2-config --cflags)
SDL_LIBS := $(shell sdl2-config --libs)
CFLAGS := -Wall -Wextra -std=c99 $(SDL_CFLAGS)
SRCDIR := src
SOURCES := $(wildcard $(SRCDIR)/*.c)
BUILD_DIR := build
OBJECTS := $(patsubst $(SRCDIR)/%.c,$(BUILD_DIR)/%.o,$(SOURCES))
TARGET := star-invaders
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJECTS)
@echo " Linking $@"
@$(CC) $(OBJECTS) -o $@ $(SDL_LIBS)
$(BUILD_DIR)/%.o: $(SRCDIR)/%.c | $(BUILD_DIR)
@echo " Compiling $<"
@$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR):
@mkdir -p $(BUILD_DIR)
clean:
@echo "Cleaning up"
@rm -rf $(BUILD_DIR) $(TARGET)

BIN
res/background.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1,6 +1,6 @@
#include "bullet.h" #include "bullet.h"
void updateBullets(Bullet* bullets, int* bulletCount, SDL_Renderer* renderer) { void updateBullets(Bullet *bullets, int *bulletCount, SDL_Renderer* renderer) {
int bulletSpeed = 7; int bulletSpeed = 7;
for (int i = 0; i < *bulletCount; i++) { for (int i = 0; i < *bulletCount; i++) {
@ -20,7 +20,7 @@ void updateBullets(Bullet* bullets, int* bulletCount, SDL_Renderer* renderer) {
} }
} }
void fireBullet(Bullet* bullets, int* bulletCount, SDL_Rect* rect) { void fireBullet(Bullet *bullets, int *bulletCount, SDL_Rect* rect) {
if (*bulletCount < MAX_BULLETS) { if (*bulletCount < MAX_BULLETS) {
bullets[*bulletCount].rect.x = rect->x + rect->w / 2 - 2; bullets[*bulletCount].rect.x = rect->x + rect->w / 2 - 2;
bullets[*bulletCount].rect.y = rect->y - 10; bullets[*bulletCount].rect.y = rect->y - 10;
@ -30,3 +30,13 @@ void fireBullet(Bullet* bullets, int* bulletCount, SDL_Rect* rect) {
(*bulletCount)++; (*bulletCount)++;
} }
} }
void cleanupUnrenderedBullets(Bullet* bullets, int* bulletCount) {
for (int i = 0; i < *bulletCount; i++){
if(bullets[i].active == 0){
memmove(&bullets[i], &bullets[i + 1], sizeof(Bullet) * (*bulletCount - i - 1));
(*bulletCount)--;
i--;
}
}
}

View File

@ -1,16 +1,17 @@
#ifndef BULLET_H #ifndef BULLET_H
#define BULLET_H #define BULLET_H
#include <SDL2/SDL.h> #include <SDL.h>
#define MAX_BULLETS 100 #define MAX_BULLETS 5
typedef struct { typedef struct {
SDL_Rect rect; SDL_Rect rect;
int active; int active;
} Bullet; } Bullet;
void updateBullets(Bullet* bullets, int* bulletCount, SDL_Renderer* renderer); void updateBullets(Bullet *bullets, int *bulletCount, SDL_Renderer *renderer);
void fireBullet(Bullet* bullets, int* bulletCount, SDL_Rect* rect); void fireBullet(Bullet *bullets, int *bulletCount, SDL_Rect *rect);
void cleanupUnrenderedBullets(Bullet* bullets, int* bulletCount);
#endif #endif

View File

@ -1,121 +1,205 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include "bullet.h" #include "bullet.h"
#include "player.h" #include "player.h"
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FPS 60 #define FPS 60
#define FRAME_DELAY (1000 / FPS) // Milliseconds per frame #define FRAME_DELAY (1000 / FPS) // Milliseconds per frame
#define SCREEN_WIDTH 800 #define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600 #define SCREEN_HEIGHT 600
void handlePlayer(SDL_Renderer* renderer, Player* player, int speed) { void handlePlayer(SDL_Renderer *renderer, Player *player, int speed, const Uint8 *keys) {
// Get current keyboard state if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) {
const Uint8* keys = SDL_GetKeyboardState(NULL); movePlayerLeft(player, speed);
}
if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) {
movePlayerRight(player, speed, SCREEN_WIDTH);
}
if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) { // Render player flipped vertically
movePlayerLeft(player, speed); renderPlayerFlipped(renderer, player, SDL_FLIP_VERTICAL);
}
if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) {
movePlayerRight(player, speed, SCREEN_WIDTH);
}
// Render player flipped vertically
renderPlayerFlipped(renderer, player, SDL_FLIP_VERTICAL);
} }
int main(int argc, char* argv[]) { int main(int argc, char *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) { if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError()); fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
return EXIT_FAILURE; return EXIT_FAILURE;
}
char *resLocation = "./res/";
for (int args = 1; args < argc; args++) {
if (strcmp(argv[args], "--help") == 0 ||
strcmp(argv[args], "-h") == 0) {
printf("Star Invaders Help:\n");
printf("Use arrow keys or A/D to move the spaceship left and right.\n");
printf("Press SPACE to fire bullets.\n");
printf("Press ESC or close the window to exit the game.\n");
printf("Use --res-location or -rl to specify the resource location.\n");
SDL_Quit();
return EXIT_SUCCESS;
} else if (strcmp(argv[args], "--version") == 0 ||
strcmp(argv[args], "-v") == 0) {
printf("Star Invaders Version 1.0.0\n");
SDL_Quit();
return EXIT_SUCCESS;
} else if (strcmp(argv[args], "--res-location") == 0 ||
strcmp(argv[args], "-rl") == 0) {
resLocation = argv[args + 1];
args++;
} else {
printf("Unknown argument: %s\n", argv[args]);
printf("Use --help or -h for usage information.\n");
SDL_Quit();
return EXIT_FAILURE;
} }
}
printf("Using resource location: %s\n", resLocation);
SDL_Window* window = SDL_CreateWindow("Star Invaders", // Build full paths for assets
SDL_WINDOWPOS_CENTERED, size_t pathLen;
SDL_WINDOWPOS_CENTERED, char *spaceshipPath;
SCREEN_WIDTH, SCREEN_HEIGHT, char *backgroundPath;
SDL_WINDOW_SHOWN); const char *shipFile = "spaceship.bmp";
if (!window) { const char *bgFile = "background.bmp";
fprintf(stderr, "Could not create window: %s\n", SDL_GetError());
SDL_Quit();
return EXIT_FAILURE;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); pathLen = strlen(resLocation) + strlen(shipFile) + 2;
if (!renderer) { spaceshipPath = (char *)malloc(pathLen);
fprintf(stderr, "Could not create renderer: %s\n", SDL_GetError()); if (!spaceshipPath) {
SDL_DestroyWindow(window); fprintf(stderr, "Out of memory\n");
SDL_Quit(); SDL_Quit();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (resLocation[strlen(resLocation) - 1] == '/') {
snprintf(spaceshipPath, pathLen, "%s%s", resLocation, shipFile);
} else {
snprintf(spaceshipPath, pathLen, "%s/%s", resLocation, shipFile);
}
// Rectangle position and size pathLen = strlen(resLocation) + strlen(bgFile) + 2;
SDL_Rect rect = {400, 500, 50, 50}; backgroundPath = (char *)malloc(pathLen);
int speed = 5; if (!backgroundPath) {
free(spaceshipPath);
fprintf(stderr, "Out of memory\n");
SDL_Quit();
return EXIT_FAILURE;
}
if (resLocation[strlen(resLocation) - 1] == '/') {
snprintf(backgroundPath, pathLen, "%s%s", resLocation, bgFile);
} else {
snprintf(backgroundPath, pathLen, "%s/%s", resLocation, bgFile);
}
// Bullets array SDL_Window *window = SDL_CreateWindow("Star Invaders", SDL_WINDOWPOS_CENTERED,
Bullet bullets[MAX_BULLETS]; SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
int bulletCount = 0; SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
for (int i = 0; i < MAX_BULLETS; i++) { if (!window) {
bullets[i].active = 0; fprintf(stderr, "Could not create window: %s\n", SDL_GetError());
} SDL_Quit();
return EXIT_FAILURE;
}
// Create player SDL_Renderer *renderer =
Player* player = createPlayer(renderer, "../res/spaceship.bmp", 400, 500); SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!player) { if (!renderer) {
SDL_DestroyRenderer(renderer); fprintf(stderr, "Could not create renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_FAILURE;
}
// Main loop flag
int running = 1;
SDL_Event event;
Uint32 frameStart;
int frameTime;
int spacePressedLastFrame = 0;
// Main loop
while (running) {
frameStart = SDL_GetTicks();
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = 0;
}
}
// Get current keyboard state for space key
const Uint8* keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_SPACE] && !spacePressedLastFrame) {
fireBullet(bullets, &bulletCount, &player->rect);
}
spacePressedLastFrame = keys[SDL_SCANCODE_SPACE];
// Clear screen with black
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Update and draw bullets
updateBullets(bullets, &bulletCount, renderer);
// Handle player movement and rendering
handlePlayer(renderer, player, speed);
// Present the rendered frame
SDL_RenderPresent(renderer);
// Cap framerate at 60 FPS
frameTime = SDL_GetTicks() - frameStart;
if (frameTime < FRAME_DELAY) {
SDL_Delay(FRAME_DELAY - frameTime);
}
}
destroyPlayer(player);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
return EXIT_SUCCESS; return EXIT_FAILURE;
}
int speed = 5;
// Bullets array
Bullet bullets[MAX_BULLETS];
int bulletCount = 0;
for (int i = 0; i < MAX_BULLETS; i++) {
bullets[i].active = 0;
}
// Create player
Player *player = createPlayer(renderer, spaceshipPath, 400, 500);
if (!player) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
free(spaceshipPath);
free(backgroundPath);
SDL_Quit();
return EXIT_FAILURE;
}
// Load background
SDL_Texture *background = NULL;
SDL_Surface *bgSurface = SDL_LoadBMP(backgroundPath);
if (!bgSurface) {
fprintf(stderr, "Could not load background %s: %s\n", backgroundPath, SDL_GetError());
} else {
background = SDL_CreateTextureFromSurface(renderer, bgSurface);
SDL_FreeSurface(bgSurface);
if (!background) {
fprintf(stderr, "Could not create background texture: %s\n", SDL_GetError());
}
}
// Main loop flag
int running = 1;
SDL_Event event;
Uint32 frameStart;
int frameTime;
int spacePressedLastFrame = 0;
// Main loop
while (running) {
frameStart = SDL_GetTicks();
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = 0;
}
}
// Get current keyboard state for space key
const Uint8 *keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_SPACE] && !spacePressedLastFrame) {
fireBullet(bullets, &bulletCount, &player->rect);
}
spacePressedLastFrame = keys[SDL_SCANCODE_SPACE];
// Clear screen with black
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Draw background if available
if (background) {
SDL_RenderCopy(renderer, background, NULL, NULL);
}
// Update and draw bullets
updateBullets(bullets, &bulletCount, renderer);
cleanupUnrenderedBullets(bullets, &bulletCount);
// Handle player movement and rendering
handlePlayer(renderer, player, speed, keys);
// Present the rendered frame
SDL_RenderPresent(renderer);
// Cap framerate at 60 FPS
frameTime = SDL_GetTicks() - frameStart;
if (frameTime < FRAME_DELAY) {
SDL_Delay(FRAME_DELAY - frameTime);
}
}
destroyPlayer(player);
if (background) {
SDL_DestroyTexture(background);
}
free(spaceshipPath);
free(backgroundPath);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
} }

View File

@ -2,56 +2,59 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
Player* createPlayer(SDL_Renderer* renderer, const char* imagePath, int x, int y) { Player *createPlayer(SDL_Renderer *renderer, const char *imagePath, int x,
Player* player = (Player*)malloc(sizeof(Player)); int y) {
Player *player = (Player *)malloc(sizeof(Player));
SDL_Surface* surface = SDL_LoadBMP(imagePath); SDL_Surface *surface = SDL_LoadBMP(imagePath);
if (!surface) { if (!surface) {
fprintf(stderr, "Could not load image %s: %s\n", imagePath, SDL_GetError()); fprintf(stderr, "Could not load image %s: %s\n", imagePath, SDL_GetError());
free(player); free(player);
return NULL; return NULL;
} }
player->texture = SDL_CreateTextureFromSurface(renderer, surface); player->texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
if (!player->texture) { if (!player->texture) {
fprintf(stderr, "Could not create texture: %s\n", SDL_GetError()); fprintf(stderr, "Could not create texture: %s\n", SDL_GetError());
free(player); free(player);
return NULL; return NULL;
} }
player->rect.x = x; player->rect.x = x;
player->rect.y = y; player->rect.y = y;
player->rect.w = 50; player->rect.w = 50;
player->rect.h = 50; player->rect.h = 50;
return player; return player;
} }
void renderPlayer(SDL_Renderer* renderer, Player* player) { void renderPlayer(SDL_Renderer *renderer, Player *player) {
SDL_RenderCopy(renderer, player->texture, NULL, &player->rect); SDL_RenderCopy(renderer, player->texture, NULL, &player->rect);
} }
void renderPlayerFlipped(SDL_Renderer* renderer, Player* player, SDL_RendererFlip flip) { void renderPlayerFlipped(SDL_Renderer *renderer, Player *player,
SDL_RenderCopyEx(renderer, player->texture, NULL, &player->rect, 0, NULL, flip); SDL_RendererFlip flip) {
SDL_RenderCopyEx(renderer, player->texture, NULL, &player->rect, 0, NULL,
flip);
} }
void movePlayerLeft(Player* player, int speed) { void movePlayerLeft(Player *player, int speed) {
if (player->rect.x - speed >= 0) { if (player->rect.x - speed >= 0) {
player->rect.x -= speed; player->rect.x -= speed;
} }
} }
void movePlayerRight(Player* player, int speed, int screenWidth) { void movePlayerRight(Player *player, int speed, int screenWidth) {
if (player->rect.x + player->rect.w + speed <= screenWidth) { if (player->rect.x + player->rect.w + speed <= screenWidth) {
player->rect.x += speed; player->rect.x += speed;
} }
} }
void destroyPlayer(Player* player) { void destroyPlayer(Player *player) {
if (player) { if (player) {
SDL_DestroyTexture(player->texture); SDL_DestroyTexture(player->texture);
free(player); free(player);
} }
} }

View File

@ -1,18 +1,20 @@
#ifndef PLAYER_H #ifndef PLAYER_H
#define PLAYER_H #define PLAYER_H
#include <SDL2/SDL.h> #include <SDL.h>
typedef struct { typedef struct {
SDL_Texture* texture; SDL_Texture *texture;
SDL_Rect rect; SDL_Rect rect;
} Player; } Player;
Player* createPlayer(SDL_Renderer* renderer, const char* imagePath, int x, int y); Player *createPlayer(SDL_Renderer *renderer, const char *imagePath, int x,
void renderPlayer(SDL_Renderer* renderer, Player* player); int y);
void renderPlayerFlipped(SDL_Renderer* renderer, Player* player, SDL_RendererFlip flip); void renderPlayer(SDL_Renderer *renderer, Player *player);
void movePlayerLeft(Player* player, int speed); void renderPlayerFlipped(SDL_Renderer *renderer, Player *player,
void movePlayerRight(Player* player, int speed, int screenWidth); SDL_RendererFlip flip);
void destroyPlayer(Player* player); void movePlayerLeft(Player *player, int speed);
void movePlayerRight(Player *player, int speed, int screenWidth);
void destroyPlayer(Player *player);
#endif #endif