Initial commit

This commit is contained in:
2025-12-06 21:35:19 +08:00
commit 9af460ac12
42 changed files with 4898 additions and 0 deletions

32
src/bullet.c Normal file
View File

@ -0,0 +1,32 @@
#include "bullet.h"
void updateBullets(Bullet* bullets, int* bulletCount, SDL_Renderer* renderer) {
int bulletSpeed = 7;
for (int i = 0; i < *bulletCount; i++) {
if (bullets[i].active) {
// Move bullet upward
bullets[i].rect.y -= bulletSpeed;
// Deactivate if bullet goes off screen
if (bullets[i].rect.y < 0) {
bullets[i].active = 0;
} else {
// Draw bullet
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
SDL_RenderFillRect(renderer, &bullets[i].rect);
}
}
}
}
void fireBullet(Bullet* bullets, int* bulletCount, SDL_Rect* rect) {
if (*bulletCount < MAX_BULLETS) {
bullets[*bulletCount].rect.x = rect->x + rect->w / 2 - 2;
bullets[*bulletCount].rect.y = rect->y - 10;
bullets[*bulletCount].rect.w = 4;
bullets[*bulletCount].rect.h = 10;
bullets[*bulletCount].active = 1;
(*bulletCount)++;
}
}

16
src/bullet.h Normal file
View File

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

121
src/main.c Normal file
View File

@ -0,0 +1,121 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include "bullet.h"
#include "player.h"
#define FPS 60
#define FRAME_DELAY (1000 / FPS) // Milliseconds per frame
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
void handlePlayer(SDL_Renderer* renderer, Player* player, int speed) {
// Get current keyboard state
const Uint8* keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) {
movePlayerLeft(player, speed);
}
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[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
return EXIT_FAILURE;
}
SDL_Window* window = SDL_CreateWindow("Star Invaders",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if (!window) {
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);
if (!renderer) {
fprintf(stderr, "Could not create renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_FAILURE;
}
// Rectangle position and size
SDL_Rect rect = {400, 500, 50, 50};
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, "../res/spaceship.bmp", 400, 500);
if (!player) {
SDL_DestroyRenderer(renderer);
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_Quit();
return EXIT_SUCCESS;
}

57
src/player.c Normal file
View File

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

18
src/player.h Normal file
View File

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