差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| youtube:crsfml-pong [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1 | youtube:crsfml-pong [2024/02/29 11:51] (現在) – freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== CrSFML Pong ====== | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | ===== src/ | ||
| + | |||
| + | |||
| + | <file crystal> | ||
| + | require " | ||
| + | require " | ||
| + | |||
| + | GAME_WIDTH | ||
| + | GAME_HEIGHT | ||
| + | PADDLE_SPEED = 300.0_f32 | ||
| + | BALL_SPEED | ||
| + | |||
| + | alias ActionMap = Hash(String, | ||
| + | |||
| + | class Paddle < SF:: | ||
| + | include SF:: | ||
| + | |||
| + | def initialize(position : SF:: | ||
| + | color : SF::Color, speed : Float32, action_map : ActionMap) | ||
| + | super() | ||
| + | |||
| + | @shape = SF:: | ||
| + | @shape.origin = {size.x / 2, size.y / 2} | ||
| + | @shape.fill_color = color | ||
| + | |||
| + | @speed = speed | ||
| + | @action_map = action_map | ||
| + | @input_direction = SF.vector2f 0, 0 | ||
| + | |||
| + | self.position = position | ||
| + | end | ||
| + | |||
| + | def process_input | ||
| + | @input_direction.y = 0 | ||
| + | if SF:: | ||
| + | @input_direction.y = -1.0 | ||
| + | end | ||
| + | if SF:: | ||
| + | @input_direction.y = +1.0 | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def update(delta_time : SF::Time) | ||
| + | dy = @input_direction.y * @speed * delta_time.as_seconds | ||
| + | move 0, dy | ||
| + | |||
| + | rect = collision_rect | ||
| + | if top(rect) < 0 | ||
| + | self.position = {position.x, | ||
| + | end | ||
| + | if bottom(rect)> | ||
| + | self.position = {position.x, | ||
| + | | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def draw(target : SF:: | ||
| + | states.transform *= transform | ||
| + | target.draw @shape, states | ||
| + | end | ||
| + | |||
| + | def collision_rect : SF:: | ||
| + | SF:: | ||
| + | end | ||
| + | end | ||
| + | |||
| + | class Ball < SF:: | ||
| + | include SF:: | ||
| + | |||
| + | def initialize(position : SF:: | ||
| + | color : SF::Color, velocity : SF:: | ||
| + | super() | ||
| + | |||
| + | @shape = SF:: | ||
| + | @shape.origin = { radius, radius } | ||
| + | @shape.fill_color = color | ||
| + | |||
| + | @velocity = velocity | ||
| + | |||
| + | self.position = position | ||
| + | end | ||
| + | |||
| + | def update(delta_time : SF::Time, paddles : Array(Paddle)) | ||
| + | update_x delta_time, paddles | ||
| + | update_y delta_time, paddles | ||
| + | end | ||
| + | |||
| + | def draw(target : SF:: | ||
| + | states.transform *= transform | ||
| + | target.draw @shape, states | ||
| + | end | ||
| + | |||
| + | private def update_x(delta_time : SF::Time, paddles : Array(Paddle)) | ||
| + | dx = @velocity.x * delta_time.as_seconds | ||
| + | move dx, 0 | ||
| + | |||
| + | paddles.each do |p| | ||
| + | c = collision_circle | ||
| + | r = p.collision_rect | ||
| + | |||
| + | if circle_rect_collide? | ||
| + | if c.center.x > right(r) | ||
| + | self.position = {right(r) + @shape.origin.x, | ||
| + | @velocity.x *= -1 | ||
| + | elsif c.center.x < left(r) | ||
| + | self.position = {left(r) - 2 * c.radius + @shape.origin.x, | ||
| + | | ||
| + | @velocity.x *= -1 | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | |||
| + | c = collision_circle | ||
| + | if c.center.x - c.radius < 0 | ||
| + | @velocity.x = +@velocity.x.abs | ||
| + | end | ||
| + | if c.center.x + c.radius > GAME_WIDTH | ||
| + | @velocity.x = -@velocity.x.abs | ||
| + | end | ||
| + | end | ||
| + | |||
| + | private def update_y(delta_time : SF::Time, paddles : Array(Paddle)) | ||
| + | dy = @velocity.y * delta_time.as_seconds | ||
| + | move 0, dy | ||
| + | |||
| + | paddles.each do |p| | ||
| + | c = collision_circle | ||
| + | r = p.collision_rect | ||
| + | |||
| + | if circle_rect_collide? | ||
| + | if c.center.y < top(r) | ||
| + | self.position = {position.x, | ||
| + | @velocity.y *= -1 | ||
| + | elsif c.center.y > bottom(r) | ||
| + | self.position = {position.x, | ||
| + | @velocity.y *= -1 | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | |||
| + | c = collision_circle | ||
| + | if c.center.y - c.radius < 0 | ||
| + | @velocity.y = +@velocity.y.abs | ||
| + | end | ||
| + | if c.center.y + c.radius > GAME_HEIGHT | ||
| + | @velocity.y = -@velocity.y.abs | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def collision_circle : Circle | ||
| + | x = position.x - @shape.origin.x + @shape.radius | ||
| + | y = position.y - @shape.origin.y + @shape.radius | ||
| + | Circle.new(SF.vector2f(x, | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def process_events(window : SF::Window) | ||
| + | while event = window.poll_event | ||
| + | if event.is_a? SF:: | ||
| + | window.close | ||
| + | end | ||
| + | |||
| + | if event.is_a? SF:: | ||
| + | if event.code == SF:: | ||
| + | window.close | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def setup_paddles : Array(Paddle) | ||
| + | paddles = [] of Paddle | ||
| + | paddles << Paddle.new( | ||
| + | SF.vector2f(40, | ||
| + | SF.vector2f(20, | ||
| + | SF:: | ||
| + | PADDLE_SPEED, | ||
| + | {" | ||
| + | ) | ||
| + | |||
| + | paddles << Paddle.new( | ||
| + | SF.vector2f(GAME_WIDTH - 40, GAME_HEIGHT / 2), | ||
| + | SF.vector2f(20, | ||
| + | SF:: | ||
| + | PADDLE_SPEED, | ||
| + | {" | ||
| + | ) | ||
| + | |||
| + | paddles | ||
| + | end | ||
| + | |||
| + | def setupo_balls : Array(Ball) | ||
| + | balls = [] of Ball | ||
| + | n = 100 | ||
| + | |||
| + | n.times do |i| | ||
| + | sx = rand(0.5 .. 3.0) | ||
| + | sy = rand(0.5 .. 3.0) | ||
| + | balls << Ball.new( | ||
| + | SF.vector2f(GAME_WIDTH / n * (i + 1), GAME_HEIGHT / 2), | ||
| + | 15.0, | ||
| + | SF:: | ||
| + | (255 - (255 / n * (i + 1))).to_i, | ||
| + | 128), | ||
| + | SF.vector2f(BALL_SPEED * sx, BALL_SPEED * sy) | ||
| + | ) | ||
| + | end | ||
| + | |||
| + | balls | ||
| + | end | ||
| + | |||
| + | ###################################################################### | ||
| + | |||
| + | window = SF:: | ||
| + | SF:: | ||
| + | ) | ||
| + | |||
| + | paddles = setup_paddles | ||
| + | balls = setupo_balls | ||
| + | |||
| + | clock = SF:: | ||
| + | elapsed_time = SF:: | ||
| + | |||
| + | while window.open? | ||
| + | # process events and players' | ||
| + | process_events window | ||
| + | paddles.each { |p| p.process_input } | ||
| + | |||
| + | # update | ||
| + | paddles.each { |p| p.update elapsed_time } | ||
| + | balls.each { |b| b.update elapsed_time, | ||
| + | |||
| + | # render | ||
| + | window.clear | ||
| + | paddles.each { |p| window.draw p } | ||
| + | balls.each { |b| window.draw b } | ||
| + | window.display | ||
| + | |||
| + | elapsed_time = clock.restart | ||
| + | end | ||
| + | </ | ||
| + | |||
| + | ===== src/ | ||
| + | |||
| + | |||
| + | <file crystal> | ||
| + | require " | ||
| + | |||
| + | def left(r : SF:: | ||
| + | r.left | ||
| + | end | ||
| + | |||
| + | def right(r : SF:: | ||
| + | r.left + r.width | ||
| + | end | ||
| + | |||
| + | def top(r : SF:: | ||
| + | r.top | ||
| + | end | ||
| + | |||
| + | def bottom(r : SF:: | ||
| + | r.top + r.height | ||
| + | end | ||
| + | |||
| + | struct Circle | ||
| + | property center : SF:: | ||
| + | property radius : Float32 | ||
| + | |||
| + | def initialize(@center, | ||
| + | end | ||
| + | end | ||
| + | |||
| + | def circle_rect_collide? | ||
| + | c = circle.center | ||
| + | |||
| + | t = c | ||
| + | t.x = left(rect) if c.x < left(rect) | ||
| + | t.x = right(rect) if c.x > right(rect) | ||
| + | t.y = top(rect) if c.y < top(rect) | ||
| + | t.y = bottom(rect) if c.y > bottom(rect) | ||
| + | |||
| + | ct = t - c | ||
| + | distance2 = ct.x ** 2 + ct.y ** 2 | ||
| + | radius2 = circle.radius ** 2 | ||
| + | |||
| + | distance2 < radius2 | ||
| + | end | ||
| + | </ | ||
| + | |||
| + | ===== shard.yml ===== | ||
| + | |||
| + | |||
| + | <file yaml> | ||
| + | name: crsfml-pong-take-5 | ||
| + | version: 0.1.0 | ||
| + | |||
| + | authors: | ||
| + | - watercat < | ||
| + | |||
| + | targets: | ||
| + | crsfml-pong-take-5: | ||
| + | main: src/ | ||
| + | |||
| + | crystal: 1.7.3 | ||
| + | |||
| + | license: WTFPL | ||
| + | |||
| + | dependencies: | ||
| + | crsfml: | ||
| + | github: oprypin/ | ||
| + | version: ~> 2.5.2 | ||
| + | </ | ||
