From 3408e77329f49b9e9cbb5baa7193c3fd5d2c5cc3 Mon Sep 17 00:00:00 2001 From: realtradam Date: Thu, 3 Mar 2022 02:23:44 -0500 Subject: init --- assets/.none | 0 main.rb | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 assets/.none create mode 100644 main.rb diff --git a/assets/.none b/assets/.none new file mode 100644 index 0000000..e69de29 diff --git a/main.rb b/main.rb new file mode 100644 index 0000000..2372842 --- /dev/null +++ b/main.rb @@ -0,0 +1,224 @@ +WindowWidth = 800 +WindowHeight = 600 +WindowTitle = 'Almost Ping Pong' +Rl.init_window(WindowWidth, WindowHeight, WindowTitle) +$frames = 0 # number of frames elapsed +$points = 0 # number of times a paddle was hit +$best_points = 0 +$dead = false +$world_rec = Rl::Rectangle.new(0, 0, WindowWidth, WindowHeight) +include FECS + +Cmp.new('Box', :obj) +Cmp.new('Position', :x, :y) +Cmp.new('Velocity', :x, :y) +Cmp.new('Paddle', :side) +Cmp.new('Ball') +Cmp.new('Color', :obj) +Cmp.new('EaseToward', :start, :finish, :time) + +Ent.new( + Cmp::Paddle.new(side: 'left'), + Cmp::Box.new(obj: Rl::Rectangle.new(0,0,25,100)), + Cmp::Position.new(x: 35, y: WindowHeight / 2), + Cmp::Color.new(obj: Rl::Color.white) +) + +Ent.new( + Cmp::Paddle.new(side: 'right'), + Cmp::Box.new(obj: Rl::Rectangle.new(0,0,25,100)), + Cmp::Position.new(x: WindowWidth - 35, y: WindowHeight / 2), + Cmp::Color.new(obj: Rl::Color.white) +) + +Ent.new( + Cmp::Ball.new, + Cmp::Box.new(obj: Rl::Rectangle.new(0,0,25,25)), + Cmp::Position.new(x: WindowWidth/2, y: WindowHeight/2), + Cmp::Velocity.new(x: 2, y: 0), + Cmp::Color.new(obj: Rl::Color.fire_brick) +) + +def ease(start:, finish:, time:) + distance = finish - start + ((1 - (1 - time)**3) * distance) + start +end + + +Scn.new('Main') + +# add all systems to a scene when they are created +Scn::Main.add( + Sys.new('Input') do + unless $dead + if Rl.key_pressed? 32 # spacebar + Scn::Main.add Sys::Move, Sys::Gravity + Cmp::Ball.first.entity.component[Cmp::Velocity].y -= 4 + end + end + if Rl.key_pressed? 82 + $dead = false + $points = 0 + Scn::Main.remove Sys::Move, Sys::Gravity + ball = Cmp::Ball.first.entity + + # make ball go right when starting + ball.component[Cmp::Velocity].x = ball.component[Cmp::Velocity].x.abs + # reset gravity + ball.component[Cmp::Velocity].y = 0 + + # move to center + ball.component[Cmp::Position].x = WindowWidth/2 + ball.component[Cmp::Position].y = WindowHeight/2 + + # slide paddles to center + Ent.group(Cmp::Paddle, Cmp::Position) do |paddle, position, entity| + if !entity.components[Cmp::EaseToward].nil? + entity.component[Cmp::EaseToward].delete + end + entity.add Cmp::EaseToward.new(start: position.y, finish: WindowHeight/2, time: 0) + end + end + end, + + Sys.new('Gravity') do + velocity = Cmp::Ball.first.entity.component[Cmp::Velocity] + unless velocity.y > 15 + velocity.y += (1.0/6.0) + end + end, + + # moving a paddle to new position + Sys.new('EaseToward') do + Ent.group(Cmp::EaseToward, Cmp::Position) do |ease, position, entity| + ease.time += Rl.frame_time * 2 + if ease.time > 1 + position.y = ease.finish + ease.delete + else + position.y = ease(start: ease.start, finish: ease.finish, time: ease.time) + end + end + end, + + Sys.new('Move') do + ball_position = Cmp::Ball.first.entity.component[Cmp::Position] + ball_velocity = Cmp::Ball.first.entity.component[Cmp::Velocity] + ball_box = Cmp::Ball.first.entity.component[Cmp::Box] + + # center the box + ball_box.obj.x = ball_position.x - (ball_box.obj.w/2) + ball_box.obj.y = ball_position.y - (ball_box.obj.h/2) + + # used for checking if where the ball will be next frame + future_ball = Rl::Rectangle.new(ball_box.obj.x + ball_velocity.x, + ball_box.obj.y + ball_velocity.y, + ball_box.obj.w, + ball_box.obj.h) + + # used for checking if we are colliding a paddle directly from above/below + future_ball_side = Rl::Rectangle.new(ball_box.obj.x, + ball_box.obj.y + ball_velocity.y, + ball_box.obj.w, + ball_box.obj.h) + + # check if possible to move, bounce off else + # iterate over all paddles that have a position and a box + Ent.group(Cmp::Paddle, Cmp::Position, Cmp::Box) do |paddle, paddle_position, paddle_box| + + # center the box + paddle_box.obj.x = paddle_position.x - (paddle_box.obj.w/2) + paddle_box.obj.y = paddle_position.y - (paddle_box.obj.h/2) + + if future_ball.collide_with_rec? paddle_box.obj + if future_ball_side.collide_with_rec? paddle_box.obj + # if it is colliding from above/below then dont bounce back + # and set horizontal speed to 0 + ball_velocity.y = 0 + else + if paddle.side == 'right' + unless ball_velocity.x < 0 + opposite = Cmp::Paddle.find { |pad| pad.side == 'left' }.entity + opposite_position = opposite.component[Cmp::Position] + opposite.add Cmp::EaseToward.new(start: opposite_position.y, finish: (60..(WindowHeight-60)).to_a.sample, time: 0) + ball_velocity.x = -ball_velocity.x.abs + $points += 1 + end + else + unless ball_velocity.x > 0 + opposite = Cmp::Paddle.find { |pad| pad.side == 'right' }.entity + opposite_position = opposite.component[Cmp::Position] + opposite.add Cmp::EaseToward.new(start: opposite_position.y, finish: (60..(WindowHeight-60)).to_a.sample, time: 0) + ball_velocity.x = ball_velocity.x.abs + $points += 1 + end + end + end + end + ball_position.x += ball_velocity.x + ball_position.y += ball_velocity.y + end + end, + + Sys.new('CheckDeath') do + # if ball outside of screen + ball_position = Cmp::Ball.first.entity.component[Cmp::Position] + ball_box = Cmp::Ball.first.entity.component[Cmp::Box] + ball_box.obj.x = ball_position.x - (ball_box.obj.w/2) + ball_box.obj.y = ball_position.y - (ball_box.obj.h/2) + + unless ball_box.obj.collide_with_rec? $world_rec + Scn::Main.remove(Sys::Move) + $dead = true + if $points > $best_points + $best_points = $points + end + end + + end, + + Sys.new('Render') do + Ent.group(Cmp::Paddle, Cmp::Position, Cmp::Box, Cmp::Color) do |paddle, position, box, color| + box.obj.x = position.x - (box.obj.w/2) + box.obj.y = position.y - (box.obj.h/2) + puts box.obj + box.obj.draw(color: color.obj) + end + Ent.group(Cmp::Ball, Cmp::Position, Cmp::Box, Cmp::Color) do |paddle, position, box, color| + box.obj.x = position.x - (box.obj.w/2) + box.obj.y = position.y - (box.obj.h/2) + box.obj.draw(color: color.obj) + end + "Points: #{$points}".draw(color: Rl::Color.dodger_blue, font_size: 48, x: 10, y: 10) + if $dead + "The Ball is Lost".draw(color: Rl::Color.fire_brick, font_size: 65, x: 130, y: 150) + "Press R to try again".draw(color: Rl::Color.fire_brick, font_size: 30, x: 205, y: 270) + "Best Score: #{$best_points}".draw(color: Rl::Color.fire_brick, font_size: 30, x: 205, y: 270 + 50) + end + end, + + Sys.new('IncrementFrame') do + $frames += 1 + end, +) + +Scn::Main.remove(Sys::Move, Sys::Gravity) # dont begin moving at the start + +# define order systems should be executed in +Order.sort( + Sys::Input, + Sys::Gravity, + Sys::EaseToward, + Sys::Move, + Sys::CheckDeath, + Sys::Render, + Sys::IncrementFrame +) + +Rl.target_fps = 60 +Rl.while_window_open do + Rl.draw(clear_color: Rl::Color.black) do + Scn::Main.call # execute the main scene once per frame + end +end + -- cgit v1.2.3