Compare commits

...

12 Commits

4 changed files with 588 additions and 122 deletions

68
Cargo.lock generated
View File

@@ -2,13 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "Test_SDL"
version = "0.1.0"
dependencies = [
"sdl2",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -21,6 +14,17 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -33,6 +37,42 @@ version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "sdl2"
version = "0.35.2"
@@ -56,8 +96,22 @@ dependencies = [
"version-compare",
]
[[package]]
name = "test_sdl"
version = "0.1.0"
dependencies = [
"rand",
"sdl2",
]
[[package]]
name = "version-compare"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"

View File

@@ -1,9 +1,10 @@
[package]
name = "Test_SDL"
name = "test_sdl"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sdl2 = "0.35.2"
sdl2 = "0.35.2"
rand = "0.8.5"

36
ReadMe.md Normal file
View File

@@ -0,0 +1,36 @@
# Rusty Golfy
A little game inspired by "Messing with sdl2" where I tested some mechanics.
The point is to have a Golf Game where you can shoot a ball against walls to get to a hole
## Run it
You need to download Rust
Then you clone this repository
And laucnh it with :
```Bash
cargo build --release
cargo run --release
```
## Controls
W,A,S,D and Arrow Keys are for modifying the shot direction and force
[DEBUG] Left Click teleports the ball to the cursors location.
[DEBUG] Right Click cancels any velocity of the ball.
[DEBUG] Press R to randomize the map (you can maintain the key pressed if you want to kill a friend who has photosensitive epilepsy)
Tab toggles a debug mode where you can see the actual vector applied to the ball wich is render as a cube to see its hitbox and tiles borders
Spacebar releases the ball and when preseed back, resets the position and velocity of the ball
## How to play
You can use your arrows keys or W,A,S,D to setup the launching angle and force and then press Space to release the ball and see it boucing around

View File

@@ -1,150 +1,523 @@
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::keyboard::Scancode;
use std::time::Duration;
use sdl2::rect::Point;
use sdl2::rect::Rect;
use rand::Rng;
const WINDOW_HEIGHT:i32 = 600;
const WINDOW_WIDTH:i32 = 800;
const BLOC_SPEED:f32 = 3.0;
const MAX_SPEED:f32 = 20.0;
const WINDOW_HEIGHT:i32 = 1000;
const BALL_SPEED:f32 = 3.0;
const MAX_SPEED:f32 = 60.0;
const DEBUG_FX_SIZE_RATIO:i32 = 2;
const BOUNCE_RATIO:f32 = 60.0;
pub struct Game{
main_bloc:Entity,
const DEFAULT_BALL_WIDTH:i32 = 20;
const DEFAULT_START_BALL_LOCATION_X:i32 = WINDOW_WIDTH / 2 - DEFAULT_BALL_WIDTH / 2;
const DEFAULT_START_BALL_LOCATION_Y:i32 = (WINDOW_HEIGHT / 5) * 4 - DEFAULT_BALL_WIDTH / 2;
const ARROW_PARTS:i32 = 10;
const ARROW_SIZE_RATIO:i32 = 3;
const ARROW_WIDTH:i32 = 3;
const DEFAULT_MAP_WIDTH:i32 = 40;
const DEFAULT_MAP_HEIGHT:i32 = 50;
const DEFAULT_TEST_MAP:&[i32] = &[
5,5,5,5,5,0,0,0,0,0, 0,0,1,1,1,1,1,1,0,0, 1,1,0,1,1,1,0,0,0,0, 0,0,0,0,0,4,4,4,4,4,
5,5,4,0,0,0,0,0,0,0, 0,0,0,1,0,1,1,0,0,1, 0,0,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,0,3,4,4,
5,4,5,4,0,0,0,0,0,0, 0,0,0,1,0,1,0,0,0,0, 1,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,3,4,3,4,
5,0,4,5,4,0,0,0,0,0, 0,0,0,1,0,1,1,1,0,1, 1,0,0,0,1,0,0,0,0,0, 0,0,0,0,0,3,4,3,0,4,
5,0,0,4,5,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,3,4,3,0,0,4,
0,0,0,0,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,3,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,2,2,2, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 3,3,3,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,2,2,2, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 3,3,3,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,2,2,2, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 3,3,3,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,6, 6,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,6, 6,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1, 5,5,5,5,5,0,0,0,0,0, 0,0,0,0,0,5,5,5,5,5, 1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,4, 4,4,4,4,4,0,0,0,0,0, 0,0,0,0,0,4,4,4,4,4, 4,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 3,3,3,3,3,0,0,0,0,0, 0,0,0,0,0,3,3,3,3,3, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 2,2,2,2,2,0,0,0,0,0, 0,0,0,0,0,2,2,2,2,2, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,4,4,4, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 5,5,5,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,4,4,4, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 5,5,5,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,4,4,4, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 5,5,5,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,2,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,0,0,0,0,
3,0,0,2,3,2,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,2,1,0,0,2,
3,0,2,3,2,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,2,1,0,2,
3,2,3,2,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,1,2,1,2,
3,3,2,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,1,2,2,
3,3,3,3,3,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,2,2,2,2,2,
];
pub struct Map{
size:Point,
grid:Vec<i32>,
}
impl Game{
pub fn render(&mut self,ctx:&mut sdl2::render::Canvas<sdl2::video::Window>){
ctx.set_draw_color(Color::RGB(0x6D, 0x6D, 0x64));
ctx.clear();
//Rendering main_bloc
ctx.set_draw_color(Color::RGB(0x33, 0x33, 0x33));
ctx.fill_rect(self.main_bloc.shape).expect("Could not fill the rectangle");
//ctx.set_draw_color(Color::RGB(0xFF, 0xFF, 0xFF));
//ctx.draw_rect(self.main_bloc.shape).expect("Could not outline the rectangle");
}
pub fn up(&mut self){
// 'w' or the up arrow has been pressed
//println!("DEBUG: Up is pressed");
self.main_bloc.velocity.y -= BLOC_SPEED as i32;
if self.main_bloc.velocity.y < -MAX_SPEED as i32{
self.main_bloc.velocity.y = -MAX_SPEED as i32;
impl Map{
fn new() -> Self{
//let (width,height) = (DEFAULT_MAP_WIDTH,DEFAULT_MAP_HEIGHT);
Map{
size:Point::new(DEFAULT_MAP_WIDTH,DEFAULT_MAP_HEIGHT),
//grid:vec![0;width as usize * height as usize],
grid:DEFAULT_TEST_MAP.to_vec(),
}
}
fn randomize(&mut self){
let mut rng = rand::thread_rng();
for x in 0..self.size.x{
for y in 0..self.size.y{
let index = x + self.size.x * y;
self.grid[index as usize] = rng.gen_range(0..6);
}
}
}
pub fn render(&mut self,ctx:&mut sdl2::render::Canvas<sdl2::video::Window>,debug:bool){
let width = WINDOW_WIDTH / self.size.x;
let height = WINDOW_HEIGHT / self.size.y;
for x in 0..self.size.x{
for y in 0..self.size.y{
let rect = Rect::new(x * width,y * height,width as u32,height as u32);
let index = x + self.size.x * y;
let debug_color:Color = Color::RGB(0xFF, 0xFF, 0xFF);
let tile_bg:Color;
match self.grid[index as usize]{
0 => {
//Ground
tile_bg = Color::RGB(0xA7,0xC9,0x57);
}
1 =>{
//Wall 43515a
tile_bg = Color::RGB(0x43, 0x51, 0x5A);
}
2 =>{
//Water 2887c8
tile_bg = Color::RGB(0x28, 0x87, 0xC8);
}
3 =>{
//Sand f2e8cf
tile_bg = Color::RGB(0xF2, 0xE8, 0xCF);
}
4 =>{
//Wet Sand DCC27F
tile_bg = Color::RGB(0xDC, 0xC2, 0x7F);
}
5 =>{
//Forest 386641
tile_bg = Color::RGB(0x38, 0x66, 0x41);
}
6 =>{
//Hole bc4749
tile_bg = Color::RGB(0xBC, 0x47, 0x49);
}
_ => {
//uuuuuuh... whatever I guess lets make it black
tile_bg = Color::RGB(0x00, 0x00, 0x00);
},
}
ctx.set_draw_color(tile_bg);
ctx.fill_rect(rect).expect("Could not render grid");
if debug{
ctx.set_draw_color(debug_color);
ctx.draw_rect(rect).expect("Could not render debug grid");
}
}
}
}
}
pub struct Game{
main_ball:Entity,
draw_debug:bool,
ball_released:bool,
map:Map,
}
impl Game{
pub fn render(&mut self,ctx:&mut sdl2::render::Canvas<sdl2::video::Window>){
let main_ball_color:Color = Color::RGB(0xFA, 0xFD, 0xF6);
let main_ball_outline:Color = Color::RGB(0x17, 0x2A, 0x33);
let background_color:Color = Color::RGB(0xFF,0xFF,0xFF);
let velocity_color:u8 = ((self.main_ball.velocity.x * 4).abs() + (self.main_ball.velocity.y * 4).abs()) as u8;
let arrow_color:Color = Color::RGB(velocity_color,0x00,0x00);
let arrow_outline:Color = Color::RGB(0x00,0x00,0x00);
ctx.set_draw_color(background_color);
ctx.clear();
//map
self.map.render(ctx,self.draw_debug);
//ball
let center:Point = Point::new(self.main_ball.shape.x + (self.main_ball.shape.width() / 2) as i32,self.main_ball.shape.y + (self.main_ball.shape.width() / 2) as i32);
if self.draw_debug {
ctx.set_draw_color(main_ball_color);
ctx.fill_rect(self.main_ball.shape).expect("Could not fill the rectangle");
ctx.set_draw_color(main_ball_outline);
ctx.draw_rect(self.main_ball.shape).expect("Could not ouline the rectangle");
let apex:Point = Point::new(center.x + (self.main_ball.velocity.x * DEBUG_FX_SIZE_RATIO) as i32,center.y + (self.main_ball.velocity.y * DEBUG_FX_SIZE_RATIO) as i32);
ctx.draw_line(center,apex).expect("Could not render the Debug FX");
}else{
fill_circle(ctx, center.x, center.y,self.main_ball.shape.width() as i32 / 2, main_ball_color);
draw_circle(ctx,center.x,center.y,self.main_ball.shape.width() as i32 / 2, main_ball_outline);
draw_circle(ctx,center.x,center.y,self.main_ball.shape.width() as i32 / 2 + 1, main_ball_outline);
let apex:Point = Point::new(center.x + (self.main_ball.velocity.x * ARROW_SIZE_RATIO) as i32,center.y + (self.main_ball.velocity.y * ARROW_SIZE_RATIO) as i32);
let offset = Point::new(((apex.x - center.x) as f32 / ARROW_PARTS as f32) as i32,((apex.y -center.y) as f32 / ARROW_PARTS as f32) as i32);
if !self.ball_released{
for i in 0..ARROW_PARTS{
ctx.set_draw_color(arrow_color);
let center = Point::new(center.x + i*offset.x,center.y + i*offset.y);
fill_circle(ctx, center.x, center.y, ARROW_WIDTH, arrow_color);
draw_circle(ctx, center.x, center.y, ARROW_WIDTH + 1, arrow_outline);
}
}
}
}
pub fn up(&mut self){
if !self.ball_released{
self.main_ball.velocity.y -= BALL_SPEED as i32;
if self.main_ball.velocity.y < -MAX_SPEED as i32{
self.main_ball.velocity.y = -MAX_SPEED as i32;
}
}
}
pub fn down(&mut self){
// 's' or the down arrow has been pressed
//println!("DEBUG: Down is pressed");
self.main_bloc.velocity.y += BLOC_SPEED as i32;
if self.main_bloc.velocity.y > MAX_SPEED as i32{
self.main_bloc.velocity.y = MAX_SPEED as i32;
if !self.ball_released{
self.main_ball.velocity.y += BALL_SPEED as i32;
if self.main_ball.velocity.y > MAX_SPEED as i32{
self.main_ball.velocity.y = MAX_SPEED as i32;
}
}
}
pub fn left(&mut self){
// 'a' or the left arrow has been pressed
//println!("DEBUG: Left is pressed");
self.main_bloc.velocity.x -= BLOC_SPEED as i32;
if self.main_bloc.velocity.x < -MAX_SPEED as i32{
self.main_bloc.velocity.x = -MAX_SPEED as i32;
if !self.ball_released{
self.main_ball.velocity.x -= BALL_SPEED as i32;
if self.main_ball.velocity.x < -MAX_SPEED as i32{
self.main_ball.velocity.x = -MAX_SPEED as i32;
}
}
}
pub fn right(&mut self){
// 'd' or the right arrow has been pressed
//println!("DEBUG: Right is pressed");
self.main_bloc.velocity.x += BLOC_SPEED as i32;
if self.main_bloc.velocity.y > MAX_SPEED as i32{
self.main_bloc.velocity.y = MAX_SPEED as i32;
if !self.ball_released{
self.main_ball.velocity.x += BALL_SPEED as i32;
if self.main_ball.velocity.y > MAX_SPEED as i32{
self.main_ball.velocity.y = MAX_SPEED as i32;
}
}
}
pub fn toggle_debug(&mut self){
self.draw_debug = !self.draw_debug;
}
pub fn release(&mut self){
if self.ball_released{
self.main_ball.velocity = Point::new(0,0);
self.main_ball.shape.set_x(DEFAULT_START_BALL_LOCATION_X);
self.main_ball.shape.set_y(DEFAULT_START_BALL_LOCATION_Y);
}
self.ball_released = !self.ball_released;
}
pub fn left_click(&mut self,mouse_position:Point){
// moves the bloc at the cursor position
self.main_ball.shape.set_x(mouse_position.x - (self.main_ball.shape.width() / 2) as i32);
self.main_ball.shape.set_y(mouse_position.y - (self.main_ball.shape.height() / 2) as i32);
}
pub fn right_click(&mut self,_mouse_position:Point){
// Removes any vectors
self.main_ball.velocity = Point::new(0,0);
}
pub fn update(&mut self){
let mut posx = self.main_bloc.shape.x;
let mut posy = self.main_bloc.shape.y;
posx += self.main_bloc.velocity.x;
posy += self.main_bloc.velocity.y;
let bloc_width:i32 = self.main_bloc.shape.width() as i32;
let bloc_height:i32 = self.main_bloc.shape.height() as i32;
let bloc = &mut self.main_ball;
let mut posx = bloc.shape.x;
let mut posy = bloc.shape.y;
let width = bloc.shape.width() as i32;
let height = bloc.shape.height() as i32;
if posx + bloc_width > WINDOW_WIDTH{
posx = WINDOW_WIDTH - bloc_width as i32;
self.main_bloc.velocity.x = 0;
}else{
if posx < 0{
posx = 0;
self.main_bloc.velocity.x = 0;
}
if posy + height >= WINDOW_HEIGHT{
//we hit rock bottom
posy = WINDOW_HEIGHT - height;
bloc.velocity.y = bounce(bloc.velocity.y);
}
if posy + bloc_height > WINDOW_HEIGHT{
posy = WINDOW_HEIGHT - bloc_height as i32;
self.main_bloc.velocity.y = 0;
}else{
if posy < 0{
posy = 0;
self.main_bloc.velocity.y = 0;
}
if posy <= 0{
//we hit top
posy = 0;
bloc.velocity.y = bounce(bloc.velocity.y);
}
if posx + width >= WINDOW_WIDTH{
//we hit right
posx = WINDOW_WIDTH - width;
bloc.velocity.x = bounce(bloc.velocity.x);
}
if posx <= 0{
//we hit left
posx = 0;
bloc.velocity.x = bounce(bloc.velocity.x);
}
if self.main_bloc.velocity.x > 0{
if self.main_bloc.velocity.x < BLOC_SPEED as i32{
self.main_bloc.velocity.x = 0;
}else{
self.main_bloc.velocity.x -= (BLOC_SPEED / 2.0) as i32;
//Apply tiles effects
let index_2d = Point::new(posx / (WINDOW_WIDTH / self.map.size.x),posy / (WINDOW_HEIGHT / self.map.size.y));
//println!("[DEBUG] x:{} y:{}",index_2d.x,index_2d.y);
let index_1d = index_2d.x + self.map.size.x * index_2d.y;
//println!("[DEBUG] index:{}",index_1d);
let mut slow_amount = 0;
//println!("[DEBUG] tile {}",self.map.grid[index_1d as usize]);
match self.map.grid[index_1d as usize]{
0 => {
//Ground
slow_amount = 1;
}
}else{
if self.main_bloc.velocity.x > -BLOC_SPEED as i32{
self.main_bloc.velocity.x = 0;
}else{
self.main_bloc.velocity.x += (BLOC_SPEED / 2.0) as i32;
2 =>{
//Water
slow_amount = 10;
}
3 =>{
//Sand
slow_amount = 3;
}
4 =>{
//Wet Sand
slow_amount = 5;
}
5 =>{
//Forest
slow_amount = 5;
}
6 =>{
//Hole
}
_ => {
//uuuuuuh... whatever I guess lets not do anything
},
}
if self.ball_released{
bloc.velocity.x = reduce_velocity(bloc.velocity.x, slow_amount);
bloc.velocity.y = reduce_velocity(bloc.velocity.y, slow_amount);
}
if bloc.velocity.x > MAX_SPEED as i32{
bloc.velocity.x = MAX_SPEED as i32;
}
if bloc.velocity.x < -MAX_SPEED as i32{
bloc.velocity.x = -MAX_SPEED as i32;
}
if bloc.velocity.y > MAX_SPEED as i32{
bloc.velocity.y = MAX_SPEED as i32;
}
if bloc.velocity.y < -MAX_SPEED as i32{
bloc.velocity.y = -MAX_SPEED as i32;
}
if self.main_bloc.velocity.y > 0{
if self.main_bloc.velocity.y < BLOC_SPEED as i32{
self.main_bloc.velocity.y = 0;
}else{
self.main_bloc.velocity.y -= (BLOC_SPEED / 2.0) as i32;
}
}else{
if self.main_bloc.velocity.y > -BLOC_SPEED as i32{
self.main_bloc.velocity.y = 0;
}else{
self.main_bloc.velocity.y += (BLOC_SPEED / 2.0) as i32;
}
if self.ball_released {
posx += bloc.velocity.x;
posy += bloc.velocity.y;
}
self.main_bloc.shape.set_x(posx);
self.main_bloc.shape.set_y(posy);
bloc.shape.set_x(posx);
bloc.shape.set_y(posy);
}
}
pub fn bounce(acceleration:i32)->i32{
-(acceleration as f32 / 100.0 * BOUNCE_RATIO) as i32
}
pub fn reduce_velocity(original:i32,amount:i32) -> i32{
if original > 0{
if original - amount < 0{
0
}else{
original - amount
}
}else if original < 0{
if original + amount > 0{
0
}else{
original + amount
}
}else{
original
}
}
//https://stackoverflow.com/questions/65723827/sdl2-function-to-draw-a-filled-circle ## Translated to Rust
pub fn fill_circle(ctx:&mut sdl2::render::Canvas<sdl2::video::Window>, x:i32, y:i32, radius:i32, color:Color)
{
ctx.set_draw_color(color);
let diameter = radius * 2;
for w in 0..diameter{
for h in 0..diameter{
let dx = radius - w; // horizontal offset
let dy = radius - h; // vertical offset
if (dx*dx + dy*dy) <= (radius * radius)
{
ctx.draw_point(Point::new(x + dx, y + dy)).expect("Trouble rendering the circle");
}
}
}
}
// https://stackoverflow.com/questions/38334081/howto-draw-circles-arcs-and-vector-graphics-in-sdl ## Translated to Rust
pub fn draw_circle(ctx:&mut sdl2::render::Canvas<sdl2::video::Window>, centre_x:i32, centre_y:i32, radius:i32, color:Color)
{
ctx.set_draw_color(color);
let diameter = radius * 2;
let mut x:i32 = radius - 1;
let mut y:i32 = 0;
let mut tx:i32 = 1;
let mut ty:i32 = 1;
let mut error:i32 = tx - diameter;
while x >= y
{
// Each of the following renders an octant of the circle
ctx.draw_point(Point::new(centre_x + x, centre_y - y)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x + x, centre_y + y)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x - x, centre_y - y)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x - x, centre_y + y)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x + y, centre_y - x)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x + y, centre_y + x)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x - y, centre_y - x)).expect("Trouble rendering the circle");
ctx.draw_point(Point::new(centre_x - y, centre_y + x)).expect("Trouble rendering the circle");
if error <= 0{
y+= 1;
error += ty;
ty += 2;
}
if error > 0{
x -= 1;
tx += 2;
error += tx - diameter;
}
}
}
pub struct Entity{
shape:Rect,
velocity:Point,
}
fn is_up_pressed(e: &sdl2::EventPump) -> bool {
e.keyboard_state().is_scancode_pressed(Scancode::W) || e.keyboard_state().is_scancode_pressed(Scancode::Up)
}
fn is_down_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::S) || e.keyboard_state().is_scancode_pressed(Scancode::Down)
}
fn is_left_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::A) || e.keyboard_state().is_scancode_pressed(Scancode::Left)
}
fn is_right_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::D) || e.keyboard_state().is_scancode_pressed(Scancode::Right)
}
fn is_random_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::R)
}
fn is_tab_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::Tab)
}
fn is_space_pressed(e: &sdl2::EventPump)-> bool{
e.keyboard_state().is_scancode_pressed(Scancode::Space)
}
fn check_mouse_left_pressed(e: &sdl2::EventPump) -> Point{
if e.mouse_state().left(){
return Point::new(e.mouse_state().x(),e.mouse_state().y());
}else{
return Point::new(-1,-1);
}
}
fn check_mouse_right_pressed(e: &sdl2::EventPump) -> Point{
if e.mouse_state().right(){
return Point::new(e.mouse_state().x(),e.mouse_state().y());
}else{
return Point::new(-1,-1);
}
}
pub fn main_loop(canvas: &mut sdl2::render::Canvas<sdl2::video::Window>,event_pump:&mut sdl2::EventPump,game:&mut Game){
'running: loop {
canvas.clear();
//let (mut up_state,mut down_state,mut left_state,mut right_state) = (false,false,false,false);
let (mut tab_state,mut space_state) = (false,false);
let mut quit = false;
loop{
if is_up_pressed(event_pump){
game.up();
}
if is_down_pressed(event_pump){
game.down();
}
if is_left_pressed(event_pump){
game.left();
}
if is_right_pressed(event_pump){
game.right();
}
if is_random_pressed(event_pump){
game.map.randomize();
}
if is_tab_pressed(event_pump){
if tab_state == false{
//Keydown
tab_state = true;
game.toggle_debug();
}
}else{
if tab_state == true{
//keyUp
tab_state = false
}
}
if is_space_pressed(event_pump){
if space_state == false{
//KeyDown
space_state = true;
game.release();
}
}else{
if space_state == true{
//KeyDown
space_state = false;
}
}
let mut mouse_position:Point = check_mouse_left_pressed(event_pump);
if mouse_position.x >=0 && mouse_position.y >= 0{
game.left_click(mouse_position);
}
mouse_position = check_mouse_right_pressed(event_pump);
if mouse_position.x >=0 && mouse_position.y >= 0{
game.right_click(mouse_position);
}
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} |
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
break 'running
},
Event::KeyDown { keycode: Some(Keycode::W), .. } | Event::KeyDown {keycode: Some(Keycode::Up), ..} => {
//pressed up
game.up();
},
Event::KeyDown { keycode: Some(Keycode::S), .. } | Event::KeyDown { keycode: Some(Keycode::Down), .. } => {
//pressed up
game.down();
},
Event::KeyDown { keycode: Some(Keycode::A), .. } | Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
//pressed up
game.left();
},
Event::KeyDown { keycode: Some(Keycode::D), .. } | Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
//pressed up
game.right();
quit = true;
break
},
_ => {}
}
@@ -157,6 +530,10 @@ pub fn main_loop(canvas: &mut sdl2::render::Canvas<sdl2::video::Window>,event_pu
canvas.present();
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
if quit{
break;
}
}
}
@@ -164,7 +541,7 @@ pub fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("Test SDL Rust", WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32)
let window = video_subsystem.window("Rusty Golfy", WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32)
.position_centered()
.build()
.unwrap();
@@ -174,15 +551,13 @@ pub fn main() {
canvas.set_draw_color(Color::RGB(0x6D, 0x6D, 0x64));
let main_bloc_width:i32 = 50;
let main_bloc_height:i32 = 50;
let main_bloc_position:Point = Point::new(WINDOW_WIDTH / 2 - main_bloc_width / 2,WINDOW_HEIGHT / 2 - main_bloc_height / 2);
let main_bloc_rectangle = Rect::new(main_bloc_position.x,main_bloc_position.y, main_bloc_width as u32, main_bloc_height as u32);
let main_bloc_velocity = Point::new(0,0);
let main_ball_rectangle = Rect::new(
DEFAULT_START_BALL_LOCATION_X,DEFAULT_START_BALL_LOCATION_Y, DEFAULT_BALL_WIDTH as u32, DEFAULT_BALL_WIDTH as u32);
let main_ball_velocity = Point::new(0,0);
let main_entity = Entity{
shape:main_bloc_rectangle,
velocity:main_bloc_velocity
shape:main_ball_rectangle,
velocity:main_ball_velocity
};
let mut game = Game{main_bloc:main_entity};
let mut game = Game{main_ball:main_entity,draw_debug:false,ball_released:false,map:Map::new()};
main_loop(&mut canvas,&mut event_pump,&mut game);
}