feat: initial commit
Signed-off-by: Harald Hoyer <harald@hoyer.xyz>
This commit is contained in:
commit
0a5382187e
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
/.direnv
|
||||
/logs
|
3
.goosehints
Normal file
3
.goosehints
Normal file
|
@ -0,0 +1,3 @@
|
|||
You are on a nix system. This project contains a `flake.nix`.
|
||||
To run any command use the nix develop shell.
|
||||
Read the projects `README.md` for further instructions.
|
4096
Cargo.lock
generated
Normal file
4096
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "bglga"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.13"
|
||||
fastrand = "2.0.1"
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# bglga
|
||||
|
||||
This project is a simple Galaga-like space shooter game built using the Bevy engine.
|
||||
|
||||
## Current State
|
||||
|
||||
The game features:
|
||||
- A player ship at the bottom of the screen that can move left and right
|
||||
- Shooting bullets upward using the spacebar or up arrow key
|
||||
- Enemy ships that spawn at the top and move downward
|
||||
- Collision detection between bullets and enemies
|
||||
|
||||
## Controls
|
||||
|
||||
- Move Left: A key or Left Arrow
|
||||
- Move Right: D key or Right Arrow
|
||||
- Shoot: Spacebar or Up Arrow
|
||||
|
||||
## How to Compile
|
||||
|
||||
```
|
||||
nix develop --command bash -c "cargo build"
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
1. Make sure you have Rust and Nix installed.
|
||||
2. Clone the repository.
|
||||
3. Navigate to the project directory.
|
||||
4. Run the game using the command: `nix develop --command bash -c "cargo run"`
|
496
flake.lock
Normal file
496
flake.lock
Normal file
|
@ -0,0 +1,496 @@
|
|||
{
|
||||
"nodes": {
|
||||
"advisory-db": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1742713221,
|
||||
"narHash": "sha256-PbtSoLB1FEAMy++3kPW6Kh+o4pPy5Ks92jeUyYIdh5E=",
|
||||
"owner": "rustsec",
|
||||
"repo": "advisory-db",
|
||||
"rev": "c8a7050cd4ecc35651f5a138a162bcb7730c5a9e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rustsec",
|
||||
"repo": "advisory-db",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1742394900,
|
||||
"narHash": "sha256-vVOAp9ahvnU+fQoKd4SEXB2JG2wbENkpqcwlkIXgUC0=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "70947c1908108c0c551ddfd73d4f750ff2ea67cd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane_2": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"nixpkgs"
|
||||
],
|
||||
"rust-overlay": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"rust-overlay"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1679255352,
|
||||
"narHash": "sha256-nkGwGuNkhNrnN33S4HIDV5NzkzMLU5mNStRn9sZwq8c=",
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "crane",
|
||||
"rev": "cec65880599a4ec6426186e24342e663464f5933",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rvolosatovs",
|
||||
"ref": "feat/wit",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixify",
|
||||
"nixpkgs-nixos"
|
||||
],
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742452566,
|
||||
"narHash": "sha256-sVuLDQ2UIWfXUBbctzrZrXM2X05YjX08K7XHMztt36E=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "7d9ba794daf5e8cc7ee728859bc688d8e26d5f06",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fenix_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"nixpkgs"
|
||||
],
|
||||
"rust-analyzer-src": "rust-analyzer-src_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1679552560,
|
||||
"narHash": "sha256-L9Se/F1iLQBZFGrnQJO8c9wE5z0Mf8OiycPGP9Y96hA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "fb49a9f5605ec512da947a21cc7e4551a3950397",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"locked": {
|
||||
"lastModified": 1678901627,
|
||||
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"macos-sdk": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1694769349,
|
||||
"narHash": "sha256-TEvVJy+NMPyzgWSk/6S29ZMQR+ICFxSdS3tw247uhFc=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/roblabla/MacOSX-SDKs/releases/download/macosx14.0/MacOSX14.0.sdk.tar.xz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/roblabla/MacOSX-SDKs/releases/download/macosx14.0/MacOSX14.0.sdk.tar.xz"
|
||||
}
|
||||
},
|
||||
"nix-filter": {
|
||||
"locked": {
|
||||
"lastModified": 1731533336,
|
||||
"narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-filter_2": {
|
||||
"locked": {
|
||||
"lastModified": 1678109515,
|
||||
"narHash": "sha256-C2X+qC80K2C1TOYZT8nabgo05Dw2HST/pSn6s+n6BO8=",
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"rev": "aa9ff6ce4a7f19af6415fb3721eaa513ea6c763c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-flake-tests": {
|
||||
"locked": {
|
||||
"lastModified": 1677844186,
|
||||
"narHash": "sha256-ErJZ/Gs1rxh561CJeWP5bohA2IcTq1rDneu1WT6CVII=",
|
||||
"owner": "antifuchs",
|
||||
"repo": "nix-flake-tests",
|
||||
"rev": "bbd9216bd0f6495bb961a8eb8392b7ef55c67afb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "antifuchs",
|
||||
"repo": "nix-flake-tests",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-log": {
|
||||
"inputs": {
|
||||
"nix-flake-tests": "nix-flake-tests",
|
||||
"nixify": "nixify_2",
|
||||
"nixlib": "nixlib_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733747205,
|
||||
"narHash": "sha256-8BRnYXnl0exUL/sRD2I382KHiY5TKWzVBQw6+6YO4yw=",
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nix-log",
|
||||
"rev": "354b9acbdb08a5567a97791546c1e23c9f476ef6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nix-log",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixify": {
|
||||
"inputs": {
|
||||
"advisory-db": "advisory-db",
|
||||
"crane": "crane",
|
||||
"fenix": "fenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"macos-sdk": "macos-sdk",
|
||||
"nix-filter": "nix-filter",
|
||||
"nix-log": "nix-log",
|
||||
"nixlib": "nixlib_3",
|
||||
"nixpkgs-darwin": "nixpkgs-darwin",
|
||||
"nixpkgs-nixos": "nixpkgs-nixos",
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743007747,
|
||||
"narHash": "sha256-wrntf3gtM1V0eppzGlYCI+tcwjhjLkT1aKCvetmQ5ks=",
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nixify",
|
||||
"rev": "7da7a12dfe45bbb6d339b810a6c4ef0a02a79b82",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nixify",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixify_2": {
|
||||
"inputs": {
|
||||
"crane": "crane_2",
|
||||
"fenix": "fenix_2",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nix-filter": "nix-filter_2",
|
||||
"nixlib": "nixlib",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1679748566,
|
||||
"narHash": "sha256-yA4yIJjNCOLoUh0py9S3SywwbPnd/6NPYbXad+JeOl0=",
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nixify",
|
||||
"rev": "80e823959511a42dfec4409fef406a14ae8240f3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rvolosatovs",
|
||||
"repo": "nixify",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixlib": {
|
||||
"locked": {
|
||||
"lastModified": 1679187309,
|
||||
"narHash": "sha256-H8udmkg5wppL11d/05MMzOMryiYvc403axjDNZy1/TQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "44214417fe4595438b31bdb9469be92536a61455",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixlib_2": {
|
||||
"locked": {
|
||||
"lastModified": 1679791877,
|
||||
"narHash": "sha256-tTV1Mf0hPWIMtqyU16Kd2JUBDWvfHlDC9pF57vcbgpQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "cc060ddbf652a532b54057081d5abd6144d01971",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixlib_3": {
|
||||
"locked": {
|
||||
"lastModified": 1742692082,
|
||||
"narHash": "sha256-s3XOULQj7BVO7myY5V4Sob0tRZ7nRpwEOIzXg/MkD/Q=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "a09310bc940f245e51b1ffea68731244ca38f2bd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1679577639,
|
||||
"narHash": "sha256-7u7bsNP0ApBnLgsHVROQ5ytoMqustmMVMgtaFS/P7EU=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8f1bcd72727c5d4cd775545595d068be410f2a7e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-22.11-darwin",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-darwin": {
|
||||
"locked": {
|
||||
"lastModified": 1742700192,
|
||||
"narHash": "sha256-UlGFMAX7kGEH77qE79ZNC1N7DGBEhH+eMMbGQtvzUes=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e8a44f32c46444d45482e6f962b52dc21ba91281",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-24.11-darwin",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-nixos": {
|
||||
"locked": {
|
||||
"lastModified": 1742751704,
|
||||
"narHash": "sha256-rBfc+H1dDBUQ2mgVITMGBPI1PGuCznf9rcWX/XIULyE=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f0946fa5f1fb876a9dc2e1850d9d3a4e3f914092",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-24.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixify": "nixify"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1742296961,
|
||||
"narHash": "sha256-gCpvEQOrugHWLimD1wTFOJHagnSEP6VYBDspq96Idu0=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "15d87419f1a123d8f888d608129c3ce3ff8f13d4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1679520343,
|
||||
"narHash": "sha256-AJGSGWRfoKWD5IVTu1wEsR990wHbX0kIaolPqNMEh0c=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "eb791f31e688ae00908eb75d4c704ef60c430a92",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixify",
|
||||
"nix-log",
|
||||
"nixify",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1679537973,
|
||||
"narHash": "sha256-R6borgcKeyMIjjPeeYsfo+mT8UdS+OwwbhhStdCfEjg=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "fbc7ae3f14d32e78c0e8d7865f865cc28a46b232",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rust-overlay_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixify",
|
||||
"nixpkgs-nixos"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742870002,
|
||||
"narHash": "sha256-eQnw8ufyLmrboODU8RKVNh2Mv7SACzdoFrRUV5zdNNE=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "b4c18f262dbebecb855136c1ed8047b99a9c75b6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
27
flake.nix
Normal file
27
flake.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
inputs.nixify.url = "github:rvolosatovs/nixify";
|
||||
|
||||
outputs = {nixify, ...}:
|
||||
nixify.lib.rust.mkFlake {
|
||||
src = ./.;
|
||||
|
||||
buildOverrides = {
|
||||
pkgs,
|
||||
pkgsCross ? pkgs,
|
||||
...
|
||||
}: {
|
||||
buildInputs ? [],
|
||||
depsBuildBuild ? [],
|
||||
...
|
||||
}:
|
||||
with pkgs.lib; {
|
||||
buildInputs =
|
||||
buildInputs
|
||||
++ optional pkgs.stdenv.hostPlatform.isDarwin pkgs.libiconv;
|
||||
|
||||
depsBuildBuild =
|
||||
depsBuildBuild
|
||||
++ optional pkgsCross.stdenv.hostPlatform.isDarwin pkgsCross.xcbuild.xcrun;
|
||||
};
|
||||
};
|
||||
}
|
212
src/main.rs
Normal file
212
src/main.rs
Normal file
|
@ -0,0 +1,212 @@
|
|||
use bevy::prelude::*;
|
||||
use std::time::Duration;
|
||||
|
||||
const WINDOW_WIDTH: f32 = 600.0;
|
||||
const WINDOW_HEIGHT: f32 = 800.0;
|
||||
const PLAYER_SPEED: f32 = 300.0;
|
||||
const BULLET_SPEED: f32 = 500.0;
|
||||
const ENEMY_SPEED: f32 = 100.0;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Player {
|
||||
speed: f32,
|
||||
shoot_cooldown: Timer,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Bullet;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Enemy;
|
||||
|
||||
#[derive(Resource)]
|
||||
struct EnemySpawnTimer {
|
||||
timer: Timer,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
title: "Galaga".into(),
|
||||
resolution: (WINDOW_WIDTH, WINDOW_HEIGHT).into(),
|
||||
..default()
|
||||
}),
|
||||
..default()
|
||||
}))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (
|
||||
move_player,
|
||||
player_shoot,
|
||||
move_bullets,
|
||||
move_enemies,
|
||||
check_bullet_collisions,
|
||||
spawn_enemies,
|
||||
))
|
||||
.insert_resource(EnemySpawnTimer {
|
||||
timer: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Repeating),
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands) {
|
||||
commands.spawn(Camera2dBundle::default());
|
||||
|
||||
// Spawn player
|
||||
commands.spawn((
|
||||
SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::rgb(0.0, 0.5, 1.0),
|
||||
custom_size: Some(Vec2::new(30.0, 30.0)),
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -300.0, 0.0)),
|
||||
..default()
|
||||
},
|
||||
Player {
|
||||
speed: PLAYER_SPEED,
|
||||
shoot_cooldown: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Once),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn move_player(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut query: Query<(&mut Transform, &Player)>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
if let Ok((mut transform, player)) = query.get_single_mut() {
|
||||
let mut direction = 0.0;
|
||||
|
||||
if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
|
||||
direction -= 1.0;
|
||||
}
|
||||
|
||||
if keyboard_input.pressed(KeyCode::KeyD) || keyboard_input.pressed(KeyCode::ArrowRight) {
|
||||
direction += 1.0;
|
||||
}
|
||||
|
||||
transform.translation.x += direction * player.speed * time.delta_seconds();
|
||||
transform.translation.x = transform.translation.x.clamp(-WINDOW_WIDTH / 2.0 + 15.0, WINDOW_WIDTH / 2.0 - 15.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn player_shoot(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut query: Query<(&Transform, &mut Player)>,
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
if let Ok((transform, mut player)) = query.get_single_mut() {
|
||||
player.shoot_cooldown.tick(time.delta());
|
||||
|
||||
if (keyboard_input.just_pressed(KeyCode::Space) || keyboard_input.just_pressed(KeyCode::ArrowUp))
|
||||
&& player.shoot_cooldown.finished() {
|
||||
// Reset cooldown
|
||||
player.shoot_cooldown.reset();
|
||||
|
||||
// Spawn bullet
|
||||
commands.spawn((
|
||||
SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::rgb(1.0, 1.0, 1.0),
|
||||
custom_size: Some(Vec2::new(5.0, 15.0)),
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::new(
|
||||
transform.translation.x,
|
||||
transform.translation.y + 20.0,
|
||||
0.0
|
||||
)),
|
||||
..default()
|
||||
},
|
||||
Bullet,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_bullets(
|
||||
mut query: Query<(Entity, &mut Transform), With<Bullet>>,
|
||||
time: Res<Time>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut transform) in query.iter_mut() {
|
||||
transform.translation.y += BULLET_SPEED * time.delta_seconds();
|
||||
|
||||
// Despawn bullets that go out of screen
|
||||
if transform.translation.y > WINDOW_HEIGHT / 2.0 {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_enemies(
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
mut timer: ResMut<EnemySpawnTimer>,
|
||||
enemy_query: Query<&Enemy>,
|
||||
) {
|
||||
timer.timer.tick(time.delta());
|
||||
|
||||
// Only spawn if timer finished and we don't have too many enemies
|
||||
if timer.timer.just_finished() {
|
||||
let x_pos = (fastrand::f32() - 0.5) * (WINDOW_WIDTH - 40.0);
|
||||
|
||||
commands.spawn((
|
||||
SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::rgb(1.0, 0.2, 0.2),
|
||||
custom_size: Some(Vec2::new(40.0, 40.0)),
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::new(
|
||||
x_pos,
|
||||
WINDOW_HEIGHT / 2.0 - 20.0,
|
||||
0.0
|
||||
)),
|
||||
..default()
|
||||
},
|
||||
Enemy,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn move_enemies(
|
||||
mut query: Query<(Entity, &mut Transform), With<Enemy>>,
|
||||
time: Res<Time>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut transform) in query.iter_mut() {
|
||||
transform.translation.y -= ENEMY_SPEED * time.delta_seconds();
|
||||
|
||||
// Despawn enemies that go out of screen
|
||||
if transform.translation.y < -WINDOW_HEIGHT / 2.0 {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_bullet_collisions(
|
||||
mut commands: Commands,
|
||||
bullet_query: Query<(Entity, &Transform), With<Bullet>>,
|
||||
enemy_query: Query<(Entity, &Transform), With<Enemy>>,
|
||||
) {
|
||||
for (bullet_entity, bullet_transform) in bullet_query.iter() {
|
||||
for (enemy_entity, enemy_transform) in enemy_query.iter() {
|
||||
let bullet_pos = bullet_transform.translation;
|
||||
let enemy_pos = enemy_transform.translation;
|
||||
|
||||
// Simple collision detection using distance
|
||||
let distance = bullet_pos.distance(enemy_pos);
|
||||
if distance < 25.0 { // Approximate collision radius
|
||||
// Despawn both bullet and enemy on collision
|
||||
commands.entity(bullet_entity).despawn();
|
||||
commands.entity(enemy_entity).despawn();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue