diff --git a/Games/Ball-And-Paddle-Game/README.md b/Games/Ball-And-Paddle-Game/README.md new file mode 100644 index 0000000000..e328991217 --- /dev/null +++ b/Games/Ball-And-Paddle-Game/README.md @@ -0,0 +1,20 @@ +# Ball and Paddle Game + +This is a simple implementation of a Ball and Paddle game using HTML, CSS, and JavaScript. The game is a classic arcade-style game where the player controls a paddle to keep the ball in play. + +## Features +- A visual representation of the ball, paddle, and game area. +- Interactive paddle control using keyboard inputs. +- Basic game logic for ball movement, collision detection, and scoring. +- Simple and intuitive UI with real-time score updates. + +## Usage +- The game interface will appear, and you can start playing by using the arrow keys to control the paddle. +- Keep the ball in play by bouncing it off the paddle to score points. +- The game ends when the ball misses the paddle and falls out of play. + +## Gameplay +- The game starts with the ball moving in a random direction. +- Use the left and right arrow keys to move the paddle and keep the ball in play. +- The ball bounces off the walls and the paddle; if it misses the paddle, the game is over. +- The objective is to score as many points as possible by keeping the ball in play. diff --git a/Games/Ball-And-Paddle-Game/index.html b/Games/Ball-And-Paddle-Game/index.html new file mode 100644 index 0000000000..52f4cb124a --- /dev/null +++ b/Games/Ball-And-Paddle-Game/index.html @@ -0,0 +1,16 @@ + + + + + + Ball and Paddle Game + + + +

Ball and Paddle Game

+
+ +
+ + + diff --git a/Games/Ball-And-Paddle-Game/script.js b/Games/Ball-And-Paddle-Game/script.js new file mode 100644 index 0000000000..f395a0dc2d --- /dev/null +++ b/Games/Ball-And-Paddle-Game/script.js @@ -0,0 +1,100 @@ +const canvas = document.getElementById("gameCanvas"); +const ctx = canvas.getContext("2d"); + +let x = canvas.width / 2; +let y = canvas.height - 30; +let dx = 2; +let dy = -2; +const ballRadius = 10; +const paddleHeight = 10; +const paddleWidth = 75; +let paddleX = (canvas.width - paddleWidth) / 2; +let rightPressed = false; +let leftPressed = false; +let score = 0; +let gameOver = false; + +document.addEventListener("keydown", keyDownHandler, false); +document.addEventListener("keyup", keyUpHandler, false); + +function keyDownHandler(e) { + if (e.key === "Right" || e.key === "ArrowRight") { + rightPressed = true; + } else if (e.key === "Left" || e.key === "ArrowLeft") { + leftPressed = true; + } +} + +function keyUpHandler(e) { + if (e.key === "Right" || e.key === "ArrowRight") { + rightPressed = false; + } else if (e.key === "Left" || e.key === "ArrowLeft") { + leftPressed = false; + } +} + +function drawBall() { + ctx.beginPath(); + ctx.arc(x, y, ballRadius, 0, Math.PI * 2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); +} + +function drawPaddle() { + ctx.beginPath(); + ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); +} + +function drawScore() { + ctx.font = "16px Arial"; + ctx.fillStyle = "#0095DD"; + ctx.fillText("Score: " + score, canvas.width - 80, 20); +} + +function drawGameOver() { + ctx.font = "24px Arial"; + ctx.fillStyle = "#FF0000"; + ctx.fillText("Game Over! Try Again", canvas.width / 2 - 100, canvas.height / 2); +} + +function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + drawBall(); + drawPaddle(); + drawScore(); + + if (gameOver) { + drawGameOver(); + return; + } + + if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) { + dx = -dx; + } + + if (y + dy < ballRadius) { + dy = -dy; + } else if (y + dy > canvas.height - ballRadius) { + if (x > paddleX && x < paddleX + paddleWidth) { + dy = -dy; + score++; + } else { + gameOver = true; + } + } + + if (rightPressed && paddleX < canvas.width - paddleWidth) { + paddleX += 7; + } else if (leftPressed && paddleX > 0) { + paddleX -= 7; + } + + x += dx; + y += dy; +} + +setInterval(draw, 10); diff --git a/Games/Ball-And-Paddle-Game/style.css b/Games/Ball-And-Paddle-Game/style.css new file mode 100644 index 0000000000..b843761a05 --- /dev/null +++ b/Games/Ball-And-Paddle-Game/style.css @@ -0,0 +1,27 @@ +body { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + background-color: #000; +} + +.game-heading { + color: yellow; + margin-bottom: 20px; +} + +.game-container { + border: 5px solid #fff; + padding: 10px; + background-color: #000; + display: flex; + justify-content: center; + align-items: center; +} + +canvas { + background-color: #000; +} \ No newline at end of file diff --git a/Games/Color-Blink-Challenge/README.md b/Games/Color-Blink-Challenge/README.md new file mode 100644 index 0000000000..55e4fc582b --- /dev/null +++ b/Games/Color-Blink-Challenge/README.md @@ -0,0 +1,6 @@ +# About Game + +The Color Blink Challenge is a fun and interactive game where you need to count how many times a specific color appears within 30 seconds. The color to count is selected randomly at the start of each round. Test your focus and speed, and try to achieve the highest score possible! + +# Screenshot +![alt text](image.png) \ No newline at end of file diff --git a/Games/Color-Blink-Challenge/bg.png b/Games/Color-Blink-Challenge/bg.png new file mode 100644 index 0000000000..26c56e0384 Binary files /dev/null and b/Games/Color-Blink-Challenge/bg.png differ diff --git a/Games/Color-Blink-Challenge/image.png b/Games/Color-Blink-Challenge/image.png new file mode 100644 index 0000000000..33a68ffe29 Binary files /dev/null and b/Games/Color-Blink-Challenge/image.png differ diff --git a/Games/Color-Blink-Challenge/index.html b/Games/Color-Blink-Challenge/index.html new file mode 100644 index 0000000000..6d3f05ce9b --- /dev/null +++ b/Games/Color-Blink-Challenge/index.html @@ -0,0 +1,51 @@ + + + + + + Color Blink Challenge + + + +
+
+

About the Game

+

+ The Color Blink Challenge is a fun and interactive game where you need to count how many times a specific color appears within 30 seconds. The color to count is selected randomly at the start of each round. Test your focus and speed, and try to achieve the highest score possible! +

+
+ +
+
+

Color Blink Challenge

+
+
+
+ + +
+
+

Count the color

+ + +
+

Score: 0

+

Time Left: 30 seconds

+
+
+
+ +
+

Colors in the Game

+ +
+
+ + + diff --git a/Games/Color-Blink-Challenge/script.js b/Games/Color-Blink-Challenge/script.js new file mode 100644 index 0000000000..f24a2627eb --- /dev/null +++ b/Games/Color-Blink-Challenge/script.js @@ -0,0 +1,91 @@ +let colors = ['red', 'green', 'blue', 'yellow', 'purple']; +let targetColor = ''; +let currentColorIndex = 0; +let score = 0; +let colorCount = 0; +let interval, timerInterval; +let timeLeft = 30; +let gameActive = false; + +document.getElementById('startButton').addEventListener('click', startGame); +document.getElementById('endButton').addEventListener('click', endGame); +document.getElementById('submitButton').addEventListener('click', submitAnswer); + +function startGame() { + if (gameActive) return; + gameActive = true; + + targetColor = colors[Math.floor(Math.random() * colors.length)]; + document.getElementById('targetColor').textContent = targetColor; + colorCount = 0; + timeLeft = 30; + document.getElementById('timer').textContent = timeLeft; + document.getElementById('userInput').disabled = true; + document.getElementById('userInput').value = ''; + + changeColor(); + interval = setInterval(changeColor, 1000); + timerInterval = setInterval(updateTimer, 1000); +} + +function endGame() { + clearInterval(interval); + clearInterval(timerInterval); + resetGame(true); // Pass true to indicate the game is fully resetting + alert(`Game Over! Your final score is ${score}`); +} + +function submitAnswer() { + if (!gameActive && timeLeft === 0) { + let userInput = parseInt(document.getElementById('userInput').value); + + if (userInput === colorCount) { + score += 10; + alert('Correct! You earned 10 points.'); + } else { + alert(`Wrong! The correct count was ${colorCount}.`); + } + document.getElementById('score').textContent = score; + resetGame(); + startGame(); // Start the next round immediately + } +} + +function resetGame(fullReset = false) { + colorCount = 0; + document.getElementById('userInput').value = ''; + document.getElementById('targetColor').textContent = ''; + document.getElementById('timer').textContent = '30'; + document.getElementById('userInput').disabled = true; + gameActive = false; + + if (fullReset) { + score = 0; + document.getElementById('score').textContent = score; + } + + document.getElementById('circle').style.backgroundColor = 'transparent'; +} + +function changeColor() { + let circle = document.getElementById('circle'); + currentColorIndex = (currentColorIndex + 1) % colors.length; + let currentColor = colors[currentColorIndex]; + circle.style.backgroundColor = currentColor; + + if (currentColor === targetColor) { + colorCount++; + } +} + +function updateTimer() { + timeLeft--; + document.getElementById('timer').textContent = timeLeft; + + if (timeLeft <= 0) { + clearInterval(interval); + clearInterval(timerInterval); + document.getElementById('userInput').disabled = false; + gameActive = false; + } +} diff --git a/Games/Color-Blink-Challenge/styles.css b/Games/Color-Blink-Challenge/styles.css new file mode 100644 index 0000000000..c4fd81aa55 --- /dev/null +++ b/Games/Color-Blink-Challenge/styles.css @@ -0,0 +1,134 @@ +body { + font-family: 'Roboto', sans-serif; + margin: 0; + padding: 0; + background-image: url('bg.png'); + background-size: cover; + background-position: center; + color: #ffffff; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.main-container { + display: flex; + justify-content: center; + align-items: stretch; + max-width: 1200px; + width: 90%; + background-color: rgba(0, 0, 0, 0.8); /* Darken background to make text readable */ + border-radius: 15px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); + overflow: hidden; +} + +.column { + flex: 1; + padding: 20px; + text-align: center; + background-color: rgba(255, 255, 255, 0.1); /* Slight transparency for background */ +} + +.left-column { + text-align: left; + border-right: 1px solid rgba(255, 255, 255, 0.2); +} + +.right-column { + text-align: right; + border-left: 1px solid rgba(255, 255, 255, 0.2); +} + +.game-container { + flex: 2; + text-align: center; + padding: 20px; +} + +.header h1 { + font-size: 2em; + margin-bottom: 10px; + color: #FFD700; + text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.7); +} + +.circle { + width: 150px; + height: 150px; + border-radius: 50%; + margin: 20px auto; + background-color: transparent; + border: 3px solid #FFD700; + transition: background-color 0.3s ease; + animation: blink 1s infinite alternate; +} + +.controls { + margin-bottom: 20px; +} + +.btn { + padding: 10px 20px; + font-size: 16px; + background-color: #FF4500; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + margin: 0 10px; + box-shadow: 0 4px #d23a00; + transition: background-color 0.3s ease, transform 0.2s ease; +} + +.btn:hover { + background-color: #FF6347; + transform: translateY(-2px); +} + +.btn:active { + box-shadow: 0 2px #d23a00; + transform: translateY(2px); +} + +.input-field { + padding: 8px; + margin: 10px 0; + width: 60px; + text-align: center; + border: 2px solid #FFD700; + border-radius: 5px; + background-color: rgba(255, 255, 255, 0.2); + color: #ffffff; +} + +.game-info { + margin-top: 20px; +} + +.score-time { + display: flex; + justify-content: space-around; + margin-top: 10px; +} + +ul { + list-style-type: none; + padding: 0; +} + +li { + margin: 5px 0; + font-size: 18px; + color: #FFD700; +} + +@keyframes blink { + 0% { + box-shadow: 0 0 5px rgba(255, 255, 0, 0.3); + } + 100% { + box-shadow: 0 0 20px rgba(255, 255, 0, 0.6); + } +} diff --git a/Games/Debris_Dodge/Assets/debris dodge.png b/Games/Debris_Dodge/Assets/debris dodge.png new file mode 100644 index 0000000000..4084447392 Binary files /dev/null and b/Games/Debris_Dodge/Assets/debris dodge.png differ diff --git a/Games/Debris_Dodge/Assets/debriss.png b/Games/Debris_Dodge/Assets/debriss.png new file mode 100644 index 0000000000..f15054948b Binary files /dev/null and b/Games/Debris_Dodge/Assets/debriss.png differ diff --git a/Games/Debris_Dodge/Gemfile b/Games/Debris_Dodge/Gemfile new file mode 100644 index 0000000000..27243f1b8e --- /dev/null +++ b/Games/Debris_Dodge/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in tank_island.gemspec +gemspec diff --git a/Games/Debris_Dodge/README.md b/Games/Debris_Dodge/README.md new file mode 100644 index 0000000000..1250c52958 --- /dev/null +++ b/Games/Debris_Dodge/README.md @@ -0,0 +1,79 @@ +# **Debris Dodge** + +--- + +
+Give you best Hit! + +## **Description ๐Ÿ“ƒ** +Tank Island is an open source 2D top down shooter game that was created with Ruby using +[Gosu](http://www.libgosu.org) game development library while writing +[this book](https://leanpub.com/developing-games-with-ruby/). + + +## **functionalities ๐ŸŽฎ** + +Top down 2D shooter game that involves blowing up tanks + +
+ +## **How to play? ๐Ÿ•น๏ธ** + +- `W` `A` `S` `D` moves your tank. +- Mouse `left click` shoots. +- `ESC` goes into menu and away from it. +- `R` respawns your tank. +- `T` spawns an enemy tank under mouse cursor. +- `F1` enters debug mode. +- `F2` toggles profiling + + +
+ +## **Screenshots ๐Ÿ“ธ** + +
Image Description +
+Image Description +
+ + + + + +
+ +## Installation + +Before installing, make sure you have: + +- Ruby installed, preferably through [rbenv](https://github.com/sstephenson/rbenv), not rvm. +- ImageMagick (`gem install rmagick` should work). +- Gosu prerequisites for [Mac](https://github.com/jlnr/gosu/wiki/Getting-Started-on-OS-X), + [Linux](https://github.com/jlnr/gosu/wiki/Getting-Started-on-Linux) or + [Windows](https://github.com/jlnr/gosu/wiki/Getting-Started-on-Windows) + +To install it, run + + $ gem install Debris_Dodge + +## Starting the game + +There are several ways to start the game. + +### Running in 800x600 window mode + + $ Debris_Dodge + +### Running with custom resolution + + $ w=1600 h=1200 Debris_Dodge + +### Running full screen with custom resolution + + $ fs=1 w=1200 h=800 Debris_Dodge + + + + + diff --git a/Games/Debris_Dodge/Rakefile b/Games/Debris_Dodge/Rakefile new file mode 100644 index 0000000000..809eb5616a --- /dev/null +++ b/Games/Debris_Dodge/Rakefile @@ -0,0 +1,2 @@ +require "bundler/gem_tasks" + diff --git a/Games/Debris_Dodge/bin/tank_island b/Games/Debris_Dodge/bin/tank_island new file mode 100644 index 0000000000..1352ca07a9 --- /dev/null +++ b/Games/Debris_Dodge/bin/tank_island @@ -0,0 +1,82 @@ +#!/usr/bin/env ruby + +require 'gosu_texture_packer' +require 'perlin_noise' +require 'gosu' + +root_dir = File.expand_path(File.join( + File.dirname(File.dirname(__FILE__)), 'lib')) + +%w( + game_states/game_state.rb + game_states/play_state.rb + entities/components/component.rb + entities/components/ai/tank_motion_state.rb + entities/game_object.rb + entities/powerups/powerup.rb + entities/box.rb + entities/bullet.rb + entities/camera.rb + entities/components/ai/gun.rb + entities/components/ai/tank_chasing_state.rb + entities/components/ai/tank_fighting_state.rb + entities/components/ai/tank_fleeing_state.rb + entities/components/ai/tank_motion_fsm.rb + entities/components/ai/tank_motion_state.rb + entities/components/ai/tank_navigating_state.rb + entities/components/ai/tank_roaming_state.rb + entities/components/ai/tank_stuck_state.rb + entities/components/ai/vision.rb + entities/components/ai_input.rb + entities/components/box_graphics.rb + entities/components/bullet_graphics.rb + entities/components/bullet_physics.rb + entities/components/bullet_sounds.rb + entities/components/component.rb + entities/components/damage_graphics.rb + entities/components/explosion_graphics.rb + entities/components/explosion_sounds.rb + entities/components/health.rb + entities/components/player_input.rb + entities/components/player_sounds.rb + entities/components/powerup_graphics.rb + entities/components/powerup_sounds.rb + entities/components/tank_graphics.rb + entities/components/tank_health.rb + entities/components/tank_physics.rb + entities/components/tank_sounds.rb + entities/components/tree_graphics.rb + entities/damage.rb + entities/explosion.rb + entities/game_object.rb + entities/hud.rb + entities/map.rb + entities/object_pool.rb + entities/powerups/fire_rate_powerup.rb + entities/powerups/health_powerup.rb + entities/powerups/powerup.rb + entities/powerups/powerup_respawn_queue.rb + entities/powerups/repair_powerup.rb + entities/powerups/tank_speed_powerup.rb + entities/radar.rb + entities/score_display.rb + entities/tank.rb + entities/tree.rb + game_states/demo_state.rb + game_states/menu_state.rb + game_states/pause_state.rb + misc/axis_aligned_bounding_box.rb + misc/game_window.rb + misc/names.rb + misc/quad_tree.rb + misc/stats.rb + misc/stereo_sample.rb + misc/utils.rb +).each do |f| + require File.join(root_dir, f) +end + +$debug = false +$window = GameWindow.new +GameState.switch(MenuState.instance) +$window.show diff --git a/Games/Debris_Dodge/lib/entities/box.rb b/Games/Debris_Dodge/lib/entities/box.rb new file mode 100644 index 0000000000..bf70c3db35 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/box.rb @@ -0,0 +1,28 @@ +class Box < GameObject + attr_reader :health, :graphics, :angle + + def initialize(object_pool, x, y) + super + @graphics = BoxGraphics.new(self) + @health = Health.new(self, object_pool, 10, true) + @angle = rand(-15..15) + end + + def on_collision(object) + return unless object.physics.speed > 1.0 + move(*Utils.point_at_distance(@x, @y, object.direction, 2)) + @box = nil + end + + def box + return @box if @box + w = @graphics.width / 2 + h = @graphics.height / 2 + # Bounding box adjusted to trim shadows + @box = [x - w + 4, y - h + 8, + x + w , y - h + 8, + x + w , y + h, + x - w + 4, y + h] + @box = Utils.rotate(@angle, @x, @y, *@box) + end +end diff --git a/Games/Debris_Dodge/lib/entities/bullet.rb b/Games/Debris_Dodge/lib/entities/bullet.rb new file mode 100644 index 0000000000..93fb0df835 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/bullet.rb @@ -0,0 +1,26 @@ +class Bullet < GameObject + attr_accessor :target_x, :target_y, :source, :speed, :fired_at + + def initialize(object_pool, source_x, source_y, target_x, target_y) + super(object_pool, source_x, source_y) + @target_x, @target_y = target_x, target_y + BulletPhysics.new(self, object_pool) + BulletGraphics.new(self) + BulletSounds.play(self, object_pool.camera) + end + + def box + [@x, @y] + end + + def explode + Explosion.new(object_pool, @x, @y, @source) + mark_for_removal + end + + def fire(source, speed) + @source = source + @speed = speed + @fired_at = Gosu.milliseconds + end +end diff --git a/Games/Debris_Dodge/lib/entities/camera.rb b/Games/Debris_Dodge/lib/entities/camera.rb new file mode 100644 index 0000000000..06ea2ead0f --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/camera.rb @@ -0,0 +1,113 @@ +class Camera + attr_accessor :x, :y, :zoom + attr_reader :target + + def target=(target) + @target = target + @x, @y = target.x, target.y + @zoom = 1 + end + + def desired_spot + if @target.physics.moving? + Utils.point_at_distance( + @target.x, @target.y, + @target.direction, + @target.physics.speed.ceil * 25) + else + [@target.x, @target.y] + end + end + + def mouse_coords + x, y = target_delta_on_screen + mouse_x_on_map = @target.x + + (x + $window.mouse_x - ($window.width / 2)) / @zoom + mouse_y_on_map = @target.y + + (y + $window.mouse_y - ($window.height / 2)) / @zoom + [mouse_x_on_map, mouse_y_on_map].map(&:round) + end + + def update + des_x, des_y = desired_spot + shift = Utils.adjust_speed( + @target.physics.speed).floor * + @target.speed_modifier + 1 + if @x < des_x + if des_x - @x < shift + @x = des_x + else + @x += shift + end + elsif @x > des_x + if @x - des_x < shift + @x = des_x + else + @x -= shift + end + end + if @y < des_y + if des_y - @y < shift + @y = des_y + else + @y += shift + end + elsif @y > des_y + if @y - des_y < shift + @y = des_y + else + @y -= shift + end + end + + zoom_delta = @zoom > 0 ? 0.01 : 1.0 + zoom_delta = Utils.adjust_speed(zoom_delta) + if $window.button_down?(Gosu::KbUp) + @zoom -= zoom_delta unless @zoom < 0.7 + elsif $window.button_down?(Gosu::KbDown) + @zoom += zoom_delta unless @zoom > 10 + else + target_zoom = @target.physics.speed > 1.1 ? 0.75 : 1.0 + if @zoom <= (target_zoom - 0.01) + @zoom += zoom_delta / 3 + elsif @zoom > (target_zoom + 0.01) + @zoom -= zoom_delta / 3 + end + end + end + + def to_s + "FPS: #{Gosu.fps}. " << + "#{@x}:#{@y} @ #{'%.2f' % @zoom}. " << + 'WASD to move, arrows to zoom.' + end + + def target_delta_on_screen + [(@x - @target.x) * @zoom, (@y - @target.y) * @zoom] + end + + def draw_crosshair + factor = 0.5 + x = $window.mouse_x + y = $window.mouse_y + c = crosshair + c.draw(x - c.width * factor / 2, + y - c.height * factor / 2, + 1000, factor, factor) + end + + def viewport + x0 = @x - ($window.width / 2) / @zoom + x1 = @x + ($window.width / 2) / @zoom + y0 = @y - ($window.height / 2) / @zoom + y1 = @y + ($window.height / 2) / @zoom + [x0, x1, y0, y1] + end + + private + + def crosshair + @crosshair ||= Gosu::Image.new( + Utils.media_path('c_dot.png'), false) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/gun.rb b/Games/Debris_Dodge/lib/entities/components/ai/gun.rb new file mode 100644 index 0000000000..8dec7a30c2 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/gun.rb @@ -0,0 +1,114 @@ +class AiGun + DECISION_DELAY = 300 + attr_reader :target, :desired_gun_angle + + def initialize(object, vision) + @object = object + @vision = vision + @desired_gun_angle = rand(0..360) + @retarget_speed = rand(1..5) + @accuracy = rand(0..10) + @aggressiveness = rand(1..5) + end + + def adjust_angle + adjust_desired_angle + adjust_gun_angle + end + + def update + if @vision.in_sight.any? + if @vision.closest_tank != @target + change_target(@vision.closest_tank) + end + else + @target = nil + end + + if @target + if (0..30 - rand(0..@accuracy)).include?( + (@desired_gun_angle - @object.gun_angle).abs.round) + distance = distance_to_target + if distance - 50 <= BulletPhysics::MAX_DIST + target_x, target_y = Utils.point_at_distance( + @object.x, @object.y, @object.gun_angle, + distance + 10 - rand(0..@accuracy)) + if can_make_new_decision? && @object.can_shoot? && + should_shoot? + @object.shoot(target_x, target_y) + end + end + end + end + end + + def draw(viewport) + if $debug + color = Gosu::Color::BLUE + x, y = @object.x, @object.y + t_x, t_y = Utils.point_at_distance(x, y, @desired_gun_angle, + BulletPhysics::MAX_DIST) + $window.draw_line(x, y, color, t_x, t_y, color, 1001) + color = Gosu::Color::RED + t_x, t_y = Utils.point_at_distance(x, y, @object.gun_angle, + BulletPhysics::MAX_DIST) + $window.draw_line(x, y, color, t_x, t_y, color, 1000) + end + end + + def distance_to_target + Utils.distance_between( + @object.x, @object.y, @target.x, @target.y) + end + + + def should_shoot? + rand * @aggressiveness > 0.3 + end + + def can_make_new_decision? + now = Gosu.milliseconds + if now - (@last_decision ||= 0) > DECISION_DELAY + @last_decision = now + true + end + end + + def adjust_desired_angle + @desired_gun_angle = if @target + Utils.angle_between( + @object.x, @object.y, @target.x, @target.y) + else + @object.direction + end + end + + def change_target(new_target) + @target = new_target + adjust_desired_angle + end + + def adjust_gun_angle + actual = @object.gun_angle + desired = @desired_gun_angle + if actual > desired + if actual - desired > 180 # 0 -> 360 fix + @object.gun_angle = (actual + @retarget_speed) % 360 + if @object.gun_angle < desired + @object.gun_angle = desired # damp + end + else + @object.gun_angle = [actual - @retarget_speed, desired].max + end + elsif actual < desired + if desired - actual > 180 # 360 -> 0 fix + @object.gun_angle = (360 + actual - @retarget_speed) % 360 + if @object.gun_angle > desired + @object.gun_angle = desired # damp + end + else + @object.gun_angle = [actual + @retarget_speed, desired].min + end + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_chasing_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_chasing_state.rb new file mode 100644 index 0000000000..36137754b5 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_chasing_state.rb @@ -0,0 +1,30 @@ +class TankChasingState < TankMotionState + def initialize(object, vision, gun) + super(object, vision) + @object = object + @vision = vision + @gun = gun + end + + def update + change_direction if should_change_direction? + drive + end + + def change_direction + @object.physics.change_direction( + @gun.desired_gun_angle - + @gun.desired_gun_angle % 45) + + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def drive_time + 10000 + end + + def turn_time + rand(300..600) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_fighting_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_fighting_state.rb new file mode 100644 index 0000000000..f7f9dbb121 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_fighting_state.rb @@ -0,0 +1,47 @@ +class TankFightingState < TankMotionState + def initialize(object, vision) + super + @object = object + @vision = vision + end + + def update + change_direction if should_change_direction? + if substate_expired? + rand > 0.1 ? drive : wait + end + end + + def change_direction + change = case rand(0..100) + when 0..20 + -45 + when 20..40 + 45 + when 40..60 + 90 + when 60..80 + -90 + when 80..90 + 135 + when 90..100 + -135 + end + @object.physics.change_direction( + @object.direction + change) + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def wait_time + rand(50..300) + end + + def drive_time + rand(5000..10000) + end + + def turn_time + rand(300..3000) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_fleeing_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_fleeing_state.rb new file mode 100644 index 0000000000..4dbe5eab0b --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_fleeing_state.rb @@ -0,0 +1,50 @@ +class TankFleeingState < TankMotionState + MAX_FLEE_TIME = 15 * 1000 # 15 seconds + + def initialize(object, vision, gun) + super(object, vision) + @object = object + @vision = vision + @gun = gun + end + + def can_flee? + return true unless @started_fleeing + Gosu.milliseconds - @started_fleeing < MAX_FLEE_TIME + end + + def enter + @started_fleeing ||= Gosu.milliseconds + end + + def update + change_direction if should_change_direction? + drive + end + + def change_direction + closest_powerup = @vision.closest_powerup( + RepairPowerup, HealthPowerup) + if closest_powerup + angle = Utils.angle_between( + @object.x, @object.y, + closest_powerup.x, closest_powerup.y) + @object.physics.change_direction( + angle - angle % 45) + else + @object.physics.change_direction( + 180 + @gun.desired_gun_angle - + @gun.desired_gun_angle % 45) + end + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def drive_time + 10000 + end + + def turn_time + rand(300..600) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_fsm.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_fsm.rb new file mode 100644 index 0000000000..08fdbfc3ff --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_fsm.rb @@ -0,0 +1,102 @@ +class TankMotionFSM + STATE_CHANGE_DELAY = 500 + LOCATION_CHECK_DELAY = 5000 + + def initialize(object, vision, gun) + @object = object + @vision = vision + @gun = gun + @roaming_state = TankRoamingState.new(object, vision) + @fighting_state = TankFightingState.new(object, vision) + @fleeing_state = TankFleeingState.new(object, vision, gun) + @chasing_state = TankChasingState.new(object, vision, gun) + @stuck_state = TankStuckState.new(object, vision, gun) + @navigating_state = TankNavigatingState.new(object, vision) + set_state(@roaming_state) + end + + def on_collision(with) + @current_state.on_collision(with) + end + + def on_damage(amount) + if @current_state == @roaming_state + set_state(@fighting_state) + end + end + + def draw(viewport) + if $debug + @image && @image.draw( + @object.x - @image.width / 2, + @object.y + @object.graphics.height / 2 - + @image.height, 100) + end + end + + def update + choose_state + @current_state.update + end + + def set_state(state) + return unless state + return if state == @current_state + @last_state_change = Gosu.milliseconds + @current_state = state + state.enter + if $debug + @image = Gosu::Image.from_text( + $window, state.class.to_s, + Gosu.default_font_name, 18) + end + end + + def choose_state + unless @vision.can_go_forward? + unless @current_state == @stuck_state + set_state(@navigating_state) + end + end + # Keep unstucking itself for a while + change_delay = STATE_CHANGE_DELAY + if @current_state == @stuck_state + change_delay *= 5 + end + now = Gosu.milliseconds + return unless now - @last_state_change > change_delay + if @last_location_update.nil? + @last_location_update = now + @last_location = @object.location + end + if now - @last_location_update > LOCATION_CHECK_DELAY + unless @last_location.nil? || @current_state.waiting? + if Utils.distance_between(*@last_location, *@object.location) < 20 + set_state(@stuck_state) + @stuck_state.stuck_at = @object.location + return + end + end + @last_location_update = now + @last_location = @object.location + end + if @gun.target + if @object.health.health > 40 + if @gun.distance_to_target > BulletPhysics::MAX_DIST + new_state = @chasing_state + else + new_state = @fighting_state + end + else + if @fleeing_state.can_flee? + new_state = @fleeing_state + else + new_state = @fighting_state + end + end + else + new_state = @roaming_state + end + set_state(new_state) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_state.rb new file mode 100644 index 0000000000..e1e65cbeb1 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_motion_state.rb @@ -0,0 +1,84 @@ +class TankMotionState + def initialize(object, vision) + @object = object + @vision = vision + end + + def enter + # Override if necessary + end + + def change_direction + # Override + end + + def wait_time + # Override and return a number + end + + def drive_time + # Override and return a number + end + + def turn_time + # Override and return a number + end + + def update + # Override + end + + def wait + @sub_state = :waiting + @started_waiting = Gosu.milliseconds + @will_wait_for = wait_time + @object.throttle_down = false + end + + def waiting? + @sub_state == :waiting + end + + def drive + @sub_state = :driving + @started_driving = Gosu.milliseconds + @will_drive_for = drive_time + @object.throttle_down = true + end + + def should_change_direction? + return true unless @vision.can_go_forward? + return true unless @changed_direction_at + Gosu.milliseconds - @changed_direction_at > + @will_keep_direction_for + end + + def substate_expired? + now = Gosu.milliseconds + case @sub_state + when :waiting + true if now - @started_waiting > @will_wait_for + when :driving + true if now - @started_driving > @will_drive_for + else + true + end + end + + def on_collision(with) + change = case rand(0..100) + when 0..30 + -90 + when 30..60 + 90 + when 60..70 + 135 + when 80..90 + -135 + else + 180 + end + @object.physics.change_direction( + @object.direction + change) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_navigating_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_navigating_state.rb new file mode 100644 index 0000000000..8e888747e7 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_navigating_state.rb @@ -0,0 +1,34 @@ +class TankNavigatingState < TankMotionState + def initialize(object, vision) + @object = object + @vision = vision + end + + def update + change_direction if should_change_direction? + drive + end + + def change_direction + closest_free_path = @vision.closest_free_path + if closest_free_path + @object.physics.change_direction( + Utils.angle_between( + @object.x, @object.y, *closest_free_path)) + end + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def wait_time + rand(10..100) + end + + def drive_time + rand(1000..2000) + end + + def turn_time + rand(300..1000) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_roaming_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_roaming_state.rb new file mode 100644 index 0000000000..1942f809f9 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_roaming_state.rb @@ -0,0 +1,83 @@ +class TankRoamingState < TankMotionState + def initialize(object, vision) + super + @object = object + @vision = vision + end + + def update + change_direction if should_change_direction? + if substate_expired? + rand > 0.2 ? drive : wait + end + end + + def required_powerups + required = [] + health = @object.health.health + if @object.fire_rate_modifier < 2 && health > 50 + required << FireRatePowerup + end + if @object.speed_modifier < 1.5 && health > 50 + required << TankSpeedPowerup + end + if health < 100 + required << RepairPowerup + end + if health < 190 + required << HealthPowerup + end + required + end + + def change_direction + closest_powerup = @vision.closest_powerup( + *required_powerups) + if closest_powerup + @seeking_powerup = true + angle = Utils.angle_between( + @object.x, @object.y, + closest_powerup.x, closest_powerup.y) + @object.physics.change_direction( + angle - angle % 45) + # Go away from inaccessable powerup + unless @vision.can_go_forward? + @seeking_powerup = false + @object.physics.change_direction( + @object.direction + 180) + end + else + @seeking_powerup = false + change = case rand(0..100) + when 0..30 + -45 + when 30..60 + 45 + when 60..80 + 90 + when 80..100 + -90 + end + @object.physics.change_direction( + @object.direction + change) + end + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def wait_time + rand(50..400) + end + + def drive_time + rand(1000..3000) + end + + def turn_time + if @seeking_powerup + rand(100..300) + else + rand(1000..3000) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/tank_stuck_state.rb b/Games/Debris_Dodge/lib/entities/components/ai/tank_stuck_state.rb new file mode 100644 index 0000000000..58c4ccfc15 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/tank_stuck_state.rb @@ -0,0 +1,45 @@ +class TankStuckState < TankMotionState + attr_accessor :stuck_at + def initialize(object, vision, gun) + super(object, vision) + @object = object + @vision = vision + @gun = gun + end + + def update + change_direction if should_change_direction? + drive + end + + def change_direction + closest_free_path = @vision.closest_free_path_away_from( + @stuck_at) + if closest_free_path + @object.physics.change_direction( + Utils.angle_between( + @object.x, @object.y, *closest_free_path)) + else + if @object.health.health > 50 && rand > 0.9 + @object.shoot(*Utils.point_at_distance( + *@object.location, + @object.gun_angle, + 150)) + end + end + @changed_direction_at = Gosu.milliseconds + @will_keep_direction_for = turn_time + end + + def wait_time + rand(10..100) + end + + def drive_time + rand(1000..2000) + end + + def turn_time + rand(1000..2000) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai/vision.rb b/Games/Debris_Dodge/lib/entities/components/ai/vision.rb new file mode 100644 index 0000000000..cd6b9a535a --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai/vision.rb @@ -0,0 +1,109 @@ +class AiVision + CACHE_TIMEOUT = 500 + POWERUP_CACHE_TIMEOUT = 50 + attr_reader :in_sight + + def initialize(viewer, object_pool, distance) + @viewer = viewer + @object_pool = object_pool + @distance = distance + end + + def can_go_forward? + in_front = Utils.point_at_distance( + *@viewer.location, @viewer.direction, 40) + @object_pool.map.can_move_to?(*in_front) && + @object_pool.nearby_point(*in_front, 40, @viewer) + .reject { |o| o.is_a? Powerup }.empty? + end + + def update + @in_sight = @object_pool.nearby(@viewer, @distance) + end + + def closest_free_path(away_from = nil) + paths = [] + 5.times do |i| + if paths.any? + return farthest_from(paths, away_from) + end + radius = 55 - i * 5 + range_x = range_y = [-radius, 0, radius] + range_x.shuffle.each do |x| + range_y.shuffle.each do |y| + x = @viewer.x + x + y = @viewer.y + y + if @object_pool.map.can_move_to?(x, y) && + @object_pool.nearby_point(x, y, radius, @viewer) + .reject { |o| o.is_a? Powerup }.empty? + if away_from + paths << [x, y] + else + return [x, y] + end + end + end + end + end + false + end + + alias :closest_free_path_away_from :closest_free_path + + def closest_tank + now = Gosu.milliseconds + @closest_tank = nil + if now - (@cache_updated_at ||= 0) > CACHE_TIMEOUT + @closest_tank = nil + @cache_updated_at = now + end + @closest_tank ||= find_closest_tank + end + + def closest_powerup(*suitable) + now = Gosu.milliseconds + @closest_powerup = nil + if now - (@powerup_cache_updated_at ||= 0) > POWERUP_CACHE_TIMEOUT + @closest_powerup = nil + @powerup_cache_updated_at = now + end + @closest_powerup ||= find_closest_powerup(*suitable) + end + + private + + def farthest_from(paths, away_from) + paths.sort do |p1, p2| + Utils.distance_between(*p1, *away_from) <=> + Utils.distance_between(*p2, *away_from) + end.first + end + + def find_closest_powerup(*suitable) + if suitable.empty? + suitable = [FireRatePowerup, + HealthPowerup, + RepairPowerup, + TankSpeedPowerup] + end + @in_sight.select do |o| + suitable.include?(o.class) + end.sort do |a, b| + x, y = @viewer.x, @viewer.y + d1 = Utils.distance_between(x, y, a.x, a.y) + d2 = Utils.distance_between(x, y, b.x, b.y) + d1 <=> d2 + end.first + end + + def find_closest_tank + @in_sight.select do |o| + o.class == Tank && !o.health.dead? + end.sort do |a, b| + x, y = @viewer.x, @viewer.y + d1 = Utils.distance_between(x, y, a.x, a.y) + d2 = Utils.distance_between(x, y, b.x, b.y) + d1 <=> d2 + end.first + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/ai_input.rb b/Games/Debris_Dodge/lib/entities/components/ai_input.rb new file mode 100644 index 0000000000..86671b7885 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/ai_input.rb @@ -0,0 +1,70 @@ +class AiInput < Component + # Dark red + NAME_COLOR = Gosu::Color.argb(0xeeb10000) + UPDATE_RATE = 10 # ms + attr_reader :name + attr_reader :stats + + def initialize(name, object_pool) + super(nil) + @object_pool = object_pool + @stats = Stats.new(name) + @name = name + @last_update = Gosu.milliseconds + end + + def control(obj) + self.object = obj + object.components << self + @vision = AiVision.new(obj, @object_pool, + rand(700..1200)) + @gun = AiGun.new(obj, @vision) + @motion = TankMotionFSM.new(obj, @vision, @gun) + end + + def on_collision(with) + return if object.health.dead? + @motion.on_collision(with) + end + + def on_damage(amount) + @motion.on_damage(amount) + @stats.add_damage(amount) + end + + def update + return respawn if object.health.dead? + @gun.adjust_angle + now = Gosu.milliseconds + return if now - @last_update < UPDATE_RATE + @last_update = now + @vision.update + @gun.update + @motion.update + end + + def draw(viewport) + @motion.draw(viewport) + @gun.draw(viewport) + @name_image ||= Gosu::Image.from_text( + @name, 20, font: Gosu.default_font_name) + @name_image.draw( + x - @name_image.width / 2 - 1, + y + object.graphics.height / 2, 100, + 1, 1, Gosu::Color::WHITE) + @name_image.draw( + x - @name_image.width / 2, + y + object.graphics.height / 2, 100, + 1, 1, NAME_COLOR) + end + + private + + def respawn + if object.health.should_respawn? + object.health.restore + object.move(*@object_pool.map.spawn_point) + PlayerSounds.respawn(object, @object_pool.camera) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/box_graphics.rb b/Games/Debris_Dodge/lib/entities/components/box_graphics.rb new file mode 100644 index 0000000000..e14a2eef79 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/box_graphics.rb @@ -0,0 +1,39 @@ +class BoxGraphics < Component + def initialize(object) + super(object) + load_sprite + end + + def draw(viewport) + @box.draw_rot(x, y, 0, object.angle) + Utils.mark_corners(object.box) if $debug + end + + def height + @box.height + end + + def width + @box.width + end + + private + + def load_sprite + frame = boxes.frame_list.sample + @box = boxes.frame(frame) + end + + def center_x + @center_x ||= x - width / 2 + end + + def center_y + @center_y ||= y - height / 2 + end + + def boxes + @@boxes ||= Gosu::TexturePacker.load_json( + Utils.media_path('boxes_barrels.json')) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/bullet_graphics.rb b/Games/Debris_Dodge/lib/entities/components/bullet_graphics.rb new file mode 100644 index 0000000000..1a0d2cc54d --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/bullet_graphics.rb @@ -0,0 +1,13 @@ +class BulletGraphics < Component + def draw(viewport) + image.draw(x - 8, y - 8, 1) + Utils.mark_corners(object.box) if $debug + end + + private + + def image + @@bullet ||= Gosu::Image.new( + Utils.media_path('bullet.png'), false) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/bullet_physics.rb b/Games/Debris_Dodge/lib/entities/components/bullet_physics.rb new file mode 100644 index 0000000000..71d399bfff --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/bullet_physics.rb @@ -0,0 +1,65 @@ +class BulletPhysics < Component + START_DIST = 20 + MAX_DIST = 500 + + def initialize(game_object, object_pool) + super(game_object) + x, y = point_at_distance(START_DIST) + object.move(x, y) + @object_pool = object_pool + if trajectory_length > MAX_DIST + object.target_x, object.target_y = point_at_distance(MAX_DIST) + end + end + + def update + fly_speed = Utils.adjust_speed(object.speed) + now = Gosu.milliseconds + @last_update ||= object.fired_at + fly_distance = (now - @last_update) * 0.001 * fly_speed + object.move(*point_at_distance(fly_distance)) + @last_update = now + check_hit + object.explode if arrived? + end + + def trajectory_length + Utils.distance_between(object.target_x, object.target_y, x, y) + end + + def point_at_distance(distance) + if distance > trajectory_length + return [object.target_x, object.target_y] + end + distance_factor = distance.to_f / trajectory_length + p_x = x + (object.target_x - x) * distance_factor + p_y = y + (object.target_y - y) * distance_factor + [p_x, p_y] + end + + private + + def check_hit + @object_pool.nearby(object, 50).each do |obj| + next if obj == object.source # Don't hit source tank + if obj.class == Tree + if Utils.distance_between(x, y, obj.x, obj.y) < 10 + return do_hit(obj) if obj.respond_to?(:health) + end + elsif Utils.point_in_poly(x, y, *obj.box) + # Direct hit - extra damage + return do_hit(obj) if obj.respond_to?(:health) + end + end + end + + def do_hit(obj) + obj.health.inflict_damage(20, object.source) + object.target_x = x + object.target_y = y + end + + def arrived? + x == object.target_x && y == object.target_y + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/bullet_sounds.rb b/Games/Debris_Dodge/lib/entities/components/bullet_sounds.rb new file mode 100644 index 0000000000..a79ea40f00 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/bullet_sounds.rb @@ -0,0 +1,15 @@ +class BulletSounds + class << self + def play(object, camera) + volume, pan = Utils.volume_and_pan(object, camera) + sound.play(object.object_id, pan, volume) + end + + private + + def sound + @@sound ||= StereoSample.new( + $window, Utils.media_path('fire.ogg')) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/component.rb b/Games/Debris_Dodge/lib/entities/components/component.rb new file mode 100644 index 0000000000..83e20e8833 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/component.rb @@ -0,0 +1,32 @@ +class Component + attr_reader :object # better performance + + def initialize(game_object = nil) + self.object = game_object + end + + def update + # override + end + + def draw(viewport) + # override + end + + protected + + def object=(obj) + if obj + @object = obj + obj.components << self + end + end + + def x + @object.x + end + + def y + @object.y + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/damage_graphics.rb b/Games/Debris_Dodge/lib/entities/components/damage_graphics.rb new file mode 100644 index 0000000000..1c9ca84f91 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/damage_graphics.rb @@ -0,0 +1,21 @@ +class DamageGraphics < Component + def initialize(object_pool) + super + @image = images.sample + @angle = rand(0..360) + end + + def draw(viewport) + @image.draw_rot(x, y, 0, @angle) + end + + private + + def images + @@images ||= (1..4).map do |i| + Gosu::Image.new( + Utils.media_path("damage#{i}.png"), false + ) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/explosion_graphics.rb b/Games/Debris_Dodge/lib/entities/components/explosion_graphics.rb new file mode 100644 index 0000000000..efbff0cfc6 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/explosion_graphics.rb @@ -0,0 +1,43 @@ +class ExplosionGraphics < Component + FRAME_DELAY = 16.66 # ms + + def initialize(game_object) + super + @current_frame = 0 + end + + def draw(viewport) + image = current_frame + image.draw( + x - image.width / 2 + 3, + y - image.height / 2 - 35, + 20) + end + + def update + now = Gosu.milliseconds + delta = now - (@last_frame ||= now) + if delta > FRAME_DELAY + @last_frame = now + end + @current_frame += (delta / FRAME_DELAY).floor + object.mark_for_removal if done? + end + + private + + def current_frame + animation[@current_frame % animation.size] + end + + def done? + @done ||= @current_frame >= animation.size + end + + def animation + @@animation ||= + Gosu::Image.load_tiles( + $window, Utils.media_path('explosion.png'), + 128, 128, false) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/explosion_sounds.rb b/Games/Debris_Dodge/lib/entities/components/explosion_sounds.rb new file mode 100644 index 0000000000..871fa58b2c --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/explosion_sounds.rb @@ -0,0 +1,16 @@ +class ExplosionSounds + class << self + def play(object, camera) + volume, pan = Utils.volume_and_pan(object, camera) + sound.play(object.object_id, pan, volume) + end + + private + + def sound + @@sound ||= StereoSample.new( + $window, Utils.media_path('explosion.ogg')) + end + end +end + diff --git a/Games/Debris_Dodge/lib/entities/components/health.rb b/Games/Debris_Dodge/lib/entities/components/health.rb new file mode 100644 index 0000000000..a116742b2e --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/health.rb @@ -0,0 +1,87 @@ +class Health < Component + attr_accessor :health + + def initialize(object, object_pool, health, explodes) + super(object) + @explodes = explodes + @object_pool = object_pool + @initial_health = @health = health + @health_updated = true + end + + def restore + @health = @initial_health + @health_updated = true + end + + def increase(amount) + @health = [@health + 25, @initial_health * 2].min + @health_updated = true + end + + def damaged? + @health < @initial_health + end + + def dead? + @health < 1 + end + + def update + update_image + end + + def inflict_damage(amount, cause) + if @health > 0 + @health_updated = true + if object.respond_to?(:input) + object.input.stats.add_damage(amount) + # Don't count damage to trees and boxes + if cause.respond_to?(:input) && cause != object + cause.input.stats.add_damage_dealt(amount) + end + end + @health = [@health - amount.to_i, 0].max + after_death(cause) if dead? + end + end + + def draw(viewport) + return unless draw? + @image && @image.draw( + x - @image.width / 2, + y - object.graphics.height / 2 - + @image.height, 100) + end + + protected + + def draw? + $debug + end + + def update_image + return unless draw? + if @health_updated + text = @health.to_s + font_size = 18 + @image = Gosu::Image.from_text( + text, + font_size, font: Gosu.default_font_name) + @health_updated = false + end + end + + def after_death(cause) + if @explodes + Thread.new do + sleep(rand(0.1..0.3)) + Explosion.new(@object_pool, x, y, cause) + sleep 0.3 + object.mark_for_removal + end + else + object.mark_for_removal + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/player_input.rb b/Games/Debris_Dodge/lib/entities/components/player_input.rb new file mode 100644 index 0000000000..471838da1f --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/player_input.rb @@ -0,0 +1,100 @@ +class PlayerInput < Component + # Dark green + NAME_COLOR = Gosu::Color.argb(0xee084408) + attr_reader :stats + + def initialize(name, camera, object_pool) + super(nil) + @name = name + @stats = Stats.new(name) + @camera = camera + @object_pool = object_pool + end + + def control(obj) + self.object = obj + obj.components << self + end + + def on_collision(with) + end + + def on_damage(amount) + @stats.add_damage(amount) + end + + def update + return respawn if object.health.dead? + d_x, d_y = @camera.target_delta_on_screen + atan = Math.atan2(($window.width / 2) - d_x - $window.mouse_x, + ($window.height / 2) - d_y - $window.mouse_y) + object.gun_angle = -atan * 180 / Math::PI + motion_buttons = [Gosu::KbW, Gosu::KbS, Gosu::KbA, Gosu::KbD] + + if any_button_down?(*motion_buttons) + object.throttle_down = true + object.physics.change_direction( + change_angle(object.direction, *motion_buttons)) + else + object.throttle_down = false + end + + if Utils.button_down?(Gosu::MsLeft) + object.shoot(*@camera.mouse_coords) + end + end + + def draw(viewport) + @name_image ||= Gosu::Image.from_text( + @name, 20, font: Gosu.default_font_name) + @name_image.draw( + x - @name_image.width / 2 - 1, + y + object.graphics.height / 2, 100, + 1, 1, Gosu::Color::WHITE) + @name_image.draw( + x - @name_image.width / 2, + y + object.graphics.height / 2, 100, + 1, 1, NAME_COLOR) + end + + private + + def respawn + if object.health.should_respawn? + object.health.restore + object.move(*@object_pool.map.spawn_point) + @camera.x, @camera.y = x, y + PlayerSounds.respawn(object, @camera) + end + end + + def any_button_down?(*buttons) + buttons.each do |b| + return true if Utils.button_down?(b) + end + false + end + + def change_angle(previous_angle, up, down, right, left) + if Utils.button_down?(up) + angle = 0.0 + angle += 45.0 if Utils.button_down?(left) + angle -= 45.0 if Utils.button_down?(right) + elsif Utils.button_down?(down) + angle = 180.0 + angle -= 45.0 if Utils.button_down?(left) + angle += 45.0 if Utils.button_down?(right) + elsif Utils.button_down?(left) + angle = 90.0 + angle += 45.0 if Utils.button_down?(up) + angle -= 45.0 if Utils.button_down?(down) + elsif Utils.button_down?(right) + angle = 270.0 + angle -= 45.0 if Utils.button_down?(up) + angle += 45.0 if Utils.button_down?(down) + end + angle = (angle + 360) % 360 if angle && angle < 0 + (angle || previous_angle) + end + +end diff --git a/Games/Debris_Dodge/lib/entities/components/player_sounds.rb b/Games/Debris_Dodge/lib/entities/components/player_sounds.rb new file mode 100644 index 0000000000..3c5d17bd3b --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/player_sounds.rb @@ -0,0 +1,16 @@ +class PlayerSounds + class << self + def respawn(object, camera) + volume, pan = Utils.volume_and_pan(object, camera) + respawn_sound.play(object.object_id, pan, volume * 0.5) + end + + private + + def respawn_sound + @@respawn ||= StereoSample.new( + $window, Utils.media_path('respawn.wav')) + end + end +end + diff --git a/Games/Debris_Dodge/lib/entities/components/powerup_graphics.rb b/Games/Debris_Dodge/lib/entities/components/powerup_graphics.rb new file mode 100644 index 0000000000..808a2262ca --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/powerup_graphics.rb @@ -0,0 +1,22 @@ +class PowerupGraphics < Component + def initialize(object, type) + super(object) + @type = type + end + + def draw(viewport) + image.draw(x - 12, y - 12, 1) + Utils.mark_corners(object.box) if $debug + end + + private + + def image + @image ||= images.frame("#{@type}.png") + end + + def images + @@images ||= Gosu::TexturePacker.load_json( + Utils.media_path('pickups.json')) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/powerup_sounds.rb b/Games/Debris_Dodge/lib/entities/components/powerup_sounds.rb new file mode 100644 index 0000000000..509272247a --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/powerup_sounds.rb @@ -0,0 +1,15 @@ +class PowerupSounds + class << self + def play(object, camera) + volume, pan = Utils.volume_and_pan(object, camera) + sound.play(object.object_id, pan, volume) + end + + private + + def sound + @@sound ||= StereoSample.new( + $window, Utils.media_path('powerup.ogg')) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/tank_graphics.rb b/Games/Debris_Dodge/lib/entities/components/tank_graphics.rb new file mode 100644 index 0000000000..09ed2ceacf --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/tank_graphics.rb @@ -0,0 +1,46 @@ +class TankGraphics < Component + def initialize(game_object) + super(game_object) + @body_normal = units.frame('tank1_body.png') + @shadow_normal = units.frame('tank1_body_shadow.png') + @gun_normal = units.frame('tank1_dualgun.png') + @body_dead = units.frame('tank1_body_destroyed.png') + @shadow_dead = units.frame('tank1_body_destroyed_shadow.png') + @gun_dead = nil + update + end + + def update + if object && object.health.dead? + @body = @body_dead + @gun = @gun_dead + @shadow = @shadow_dead + else + @body = @body_normal + @gun = @gun_normal + @shadow = @shadow_normal + end + end + + def draw(viewport) + @shadow.draw_rot(x - 1, y - 1, 0, object.direction) + @body.draw_rot(x, y, 1, object.direction) + @gun.draw_rot(x, y, 2, object.gun_angle) if @gun + Utils.mark_corners(object.box) if $debug + end + + def width + @body.width + end + + def height + @body.height + end + + private + + def units + @@units = Gosu::TexturePacker.load_json( + Utils.media_path('ground_units.json'), :precise) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/tank_health.rb b/Games/Debris_Dodge/lib/entities/components/tank_health.rb new file mode 100644 index 0000000000..4da7fa8e46 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/tank_health.rb @@ -0,0 +1,32 @@ +class TankHealth < Health + RESPAWN_DELAY = 5000 + attr_accessor :health + + def initialize(object, object_pool) + super(object, object_pool, 100, true) + end + + def should_respawn? + if @death_time + Gosu.milliseconds - @death_time > RESPAWN_DELAY + end + end + + protected + + def draw? + true + end + + def after_death(cause) + @death_time = Gosu.milliseconds + object.reset_modifiers + object.input.stats.add_death + kill = object != cause ? 1 : -1 + cause.input.stats.add_kill(kill) + Thread.new do + sleep(rand(0.1..0.3)) + Explosion.new(@object_pool, x, y, cause) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/tank_physics.rb b/Games/Debris_Dodge/lib/entities/components/tank_physics.rb new file mode 100644 index 0000000000..072a790585 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/tank_physics.rb @@ -0,0 +1,179 @@ +class TankPhysics < Component + attr_accessor :speed, :in_collision, :collides_with + + def initialize(game_object, object_pool) + super(game_object) + @object_pool = object_pool + @map = object_pool.map + @speed = 0.0 + end + + def can_move_to?(x, y) + old_x, old_y = object.x, object.y + object.move(x, y) + return false unless @map.can_move_to?(x, y) + @object_pool.nearby(object, 100).each do |obj| + next if obj.class == Bullet && obj.source == object + if collides_with_poly?(obj.box) + if obj.is_a? Powerup + obj.on_collision(object) + else + @collides_with = obj + # Allow to get unstuck + old_distance = Utils.distance_between( + obj.x, obj.y, old_x, old_y) + new_distance = Utils.distance_between( + obj.x, obj.y, x, y) + return false if new_distance < old_distance + end + else + @collides_with = nil + end + end + true + ensure + object.move(old_x, old_y) + end + + def change_direction(new_direction) + change = (new_direction - object.direction + 360) % 360 + change = 360 - change if change > 180 + if change > 90 + @speed = 0 + elsif change > 45 + @speed *= 0.33 + elsif change > 0 + @speed *= 0.66 + end + object.direction = new_direction % 360 + end + + def moving? + @speed > 0 + end + + def box_height + @box_height ||= object.graphics.height + end + + def box_width + @box_width ||= object.graphics.width + end + + # Tank box looks like H. Vertices: + # 1 2 5 6 + # 3 4 + # + # 10 9 + # 12 11 8 7 + def box + w = box_width / 2 - 1 + h = box_height / 2 - 1 + tw = 8 # track width + fd = 8 # front depth + rd = 6 # rear depth + Utils.rotate(object.direction, x, y, + x + w, y + h, #1 + x + w - tw, y + h, #2 + x + w - tw, y + h - fd, #3 + + x - w + tw, y + h - fd, #4 + x - w + tw, y + h, #5 + x - w, y + h, #6 + + x - w, y - h, #7 + x - w + tw, y - h, #8 + x - w + tw, y - h + rd, #9 + + x + w - tw, y - h + rd, #10 + x + w - tw, y - h, #11 + x + w, y - h, #12 + ) + end + + def update + if object.throttle_down && !object.health.dead? + accelerate + else + decelerate + end + if @speed > 0 + new_x, new_y = x, y + speed = apply_movement_penalty(@speed) + shift = Utils.adjust_speed(speed) * object.speed_modifier + case @object.direction.to_i + when 0 + new_y -= shift + when 45 + new_x += shift + new_y -= shift + when 90 + new_x += shift + when 135 + new_x += shift + new_y += shift + when 180 + new_y += shift + when 225 + new_y += shift + new_x -= shift + when 270 + new_x -= shift + when 315 + new_x -= shift + new_y -= shift + end + if can_move_to?(new_x, new_y) + object.move(new_x, new_y) + @in_collision = false + else + object.on_collision(@collides_with) + @speed = 0.0 + @in_collision = true + end + end + end + + private + + def apply_movement_penalty(speed) + speed * (1.0 - @map.movement_penalty(x, y)) + end + + def accelerate + @speed += 0.08 if @speed < 5 + end + + def decelerate + if @speed > 0 + @speed = [@speed - 0.5, 0].max + elsif @speed < 0 + @speed = [@speed + 0.5, 0].min + end + damp_speed + end + + def damp_speed + @speed = 0 if @speed < 0.01 + end + + def collides_with_poly?(poly) + if poly + if poly.size == 2 + px, py = poly + return Utils.point_in_poly(px, py, *box) + end + poly.each_slice(2) do |x, y| + return true if Utils.point_in_poly(x, y, *box) + end + box.each_slice(2) do |x, y| + return true if Utils.point_in_poly(x, y, *poly) + end + end + false + end + + def collides_with_point?(x, y) + Utils.point_in_poly(x, y, box) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/tank_sounds.rb b/Games/Debris_Dodge/lib/entities/components/tank_sounds.rb new file mode 100644 index 0000000000..dfeb6a7978 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/tank_sounds.rb @@ -0,0 +1,43 @@ +class TankSounds < Component + def initialize(object, object_pool) + super(object) + @object_pool = object_pool + end + + def update + id = object.object_id + if object.physics.moving? + move_volume = Utils.volume( + object, @object_pool.camera) + pan = Utils.pan(object, @object_pool.camera) + if driving_sound.paused?(id) + driving_sound.resume(id) + elsif driving_sound.stopped?(id) + driving_sound.play(id, pan, 0.5, 1, true) + end + driving_sound.volume_and_pan(id, move_volume * 0.5, pan) + else + if driving_sound.playing?(id) + driving_sound.pause(id) + end + end + end + + def collide + vol, pan = Utils.volume_and_pan( + object, @object_pool.camera) + crash_sound.play(self.object_id, pan, vol, 1, false) + end + + private + + def driving_sound + @@driving_sound ||= StereoSample.new( + $window, Utils.media_path('tank_driving.ogg')) + end + + def crash_sound + @@crash_sound ||= StereoSample.new( + $window, Utils.media_path('metal_interaction2.wav')) + end +end diff --git a/Games/Debris_Dodge/lib/entities/components/tree_graphics.rb b/Games/Debris_Dodge/lib/entities/components/tree_graphics.rb new file mode 100644 index 0000000000..9be245255a --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/components/tree_graphics.rb @@ -0,0 +1,69 @@ +class TreeGraphics < Component + SHAKE_TIME = 100 + SHAKE_COOLDOWN = 200 + SHAKE_DISTANCE = [2, 1, 0, -1, -2, -1, 0, 1, 0, -1, 0] + def initialize(object, seed) + super(object) + load_sprite(seed) + end + + def shake(direction) + now = Gosu.milliseconds + return if @shake_start && + now - @shake_start < SHAKE_TIME + SHAKE_COOLDOWN + @shake_start = now + @shake_direction = direction + @shaking = true + end + + def adjust_shake(x, y, shaking_for) + elapsed = [shaking_for, SHAKE_TIME].min / SHAKE_TIME.to_f + frame = ((SHAKE_DISTANCE.length - 1) * elapsed).floor + distance = SHAKE_DISTANCE[frame] + Utils.point_at_distance(x, y, @shake_direction, distance) + end + + def draw(viewport) + if @shaking + shaking_for = Gosu.milliseconds - @shake_start + shaking_x, shaking_y = adjust_shake( + center_x, center_y, shaking_for) + @tree.draw(shaking_x, shaking_y, 5) + if shaking_for >= SHAKE_TIME + @shaking = false + end + else + @tree.draw(center_x, center_y, 5) + end + Utils.mark_corners(object.box) if $debug + end + + def height + @tree.height + end + + def width + @tree.width + end + + private + + def load_sprite(seed) + frame_list = trees.frame_list + frame = frame_list[(frame_list.size * seed).round] + @tree = trees.frame(frame) + end + + def center_x + @center_x ||= x - @tree.width / 2 + end + + def center_y + @center_y ||= y - @tree.height / 2 + end + + def trees + @@trees ||= Gosu::TexturePacker.load_json( + Utils.media_path('trees_packed.json')) + end +end diff --git a/Games/Debris_Dodge/lib/entities/damage.rb b/Games/Debris_Dodge/lib/entities/damage.rb new file mode 100644 index 0000000000..a501ae6ae7 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/damage.rb @@ -0,0 +1,26 @@ +class Damage < GameObject + MAX_INSTANCES = 300 + @@instances = [] + + def initialize(object_pool, x, y) + super + DamageGraphics.new(self) + track(self) + end + + def effect? + true + end + + private + + def track(instance) + if @@instances.size < MAX_INSTANCES + @@instances << instance + else + out = @@instances.shift + out.mark_for_removal + @@instances << instance + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/explosion.rb b/Games/Debris_Dodge/lib/entities/explosion.rb new file mode 100644 index 0000000000..772c38351e --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/explosion.rb @@ -0,0 +1,34 @@ +class Explosion < GameObject + + def initialize(object_pool, x, y, source) + super(object_pool, x, y) + @source = source + @object_pool = object_pool + if @object_pool.map.can_move_to?(x, y) + Damage.new(@object_pool, x, y) + end + ExplosionGraphics.new(self) + ExplosionSounds.play(self, object_pool.camera) + inflict_damage + end + + def effect? + true + end + + def mark_for_removal + super + end + + private + + def inflict_damage + object_pool.nearby(self, 100).each do |obj| + if obj.respond_to?(:health) + obj.health.inflict_damage( + Math.sqrt(3 * 100 - Utils.distance_between( + obj.x, obj.y, @x, @y)), @source) + end + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/game_object.rb b/Games/Debris_Dodge/lib/entities/game_object.rb new file mode 100644 index 0000000000..05fa774bab --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/game_object.rb @@ -0,0 +1,54 @@ +class GameObject + attr_reader :x, :y, :location, :components + def initialize(object_pool, x, y) + @x, @y = x, y + @location = [x, y] + @components = [] + @object_pool = object_pool + @object_pool.add(self) + end + + def move(new_x, new_y) + return if new_x == @x && new_y == @y + @object_pool.tree_remove(self) + @x = new_x + @y = new_y + @location = [new_x, new_y] + @object_pool.tree_insert(self) + end + + def update + @components.map(&:update) + end + + def draw(viewport) + @components.each { |c| c.draw(viewport) } + end + + def removable? + @removable + end + + def mark_for_removal + @removable = true + end + + def on_collision(object) + end + + def effect? + false + end + + def box + end + + def collide + end + + protected + + def object_pool + @object_pool + end +end diff --git a/Games/Debris_Dodge/lib/entities/hud.rb b/Games/Debris_Dodge/lib/entities/hud.rb new file mode 100644 index 0000000000..6f3f1965f2 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/hud.rb @@ -0,0 +1,79 @@ +class HUD + attr_accessor :active + def initialize(object_pool, tank) + @object_pool = object_pool + @tank = tank + @radar = Radar.new(@object_pool, tank) + end + + def player=(tank) + @tank = tank + @radar.target = tank + end + + def update + @radar.update + end + + def health_image + if @health.nil? || @tank.health.health != @health + @health = @tank.health.health + @health_image = Gosu::Image.from_text( + "Health: #{@health}", 20, font: Utils.main_font) + end + @health_image + end + + def stats_image + stats = @tank.input.stats + if @stats_image.nil? || stats.changed_at <= Gosu.milliseconds + @stats_image = Gosu::Image.from_text( + "Kills: #{stats.kills}", 20, font: Utils.main_font) + end + @stats_image + end + + def fire_rate_image + if @tank.fire_rate_modifier > 1 + if @fire_rate != @tank.fire_rate_modifier + @fire_rate = @tank.fire_rate_modifier + @fire_rate_image = Gosu::Image.from_text( + "Fire rate: #{@fire_rate.round(2)}X", + 20, font: Utils.main_font) + end + else + @fire_rate_image = nil + end + @fire_rate_image + end + + def speed_image + if @tank.speed_modifier > 1 + if @speed != @tank.speed_modifier + @speed = @tank.speed_modifier + @speed_image = Gosu::Image.from_text( + "Speed: #{@speed.round(2)}X", + 20, font: Utils.main_font) + end + else + @speed_image = nil + end + @speed_image + end + + def draw + if @active + @object_pool.camera.draw_crosshair + end + @radar.draw + offset = 20 + health_image.draw(20, offset, 1000) + stats_image.draw(20, offset += 30, 1000) + if fire_rate_image + fire_rate_image.draw(20, offset += 30, 1000) + end + if speed_image + speed_image.draw(20, offset += 30, 1000) + end + end +end diff --git a/Games/Debris_Dodge/lib/entities/map.rb b/Games/Debris_Dodge/lib/entities/map.rb new file mode 100644 index 0000000000..4a55676cbe --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/map.rb @@ -0,0 +1,183 @@ +class Map + MAP_WIDTH = 30 + MAP_HEIGHT = 30 + TILE_SIZE = 128 + + def self.bounding_box + center = [MAP_WIDTH * TILE_SIZE / 2, + MAP_HEIGHT * TILE_SIZE / 2] + half_dimension = [MAP_WIDTH * TILE_SIZE, + MAP_HEIGHT * TILE_SIZE] + AxisAlignedBoundingBox.new(center, half_dimension) + end + + def initialize(object_pool) + load_tiles + @object_pool = object_pool + object_pool.map = self + @map = generate_map + generate_trees + generate_boxes + generate_powerups + end + + def spawn_points(max) + @spawn_points = (0..max).map do + find_spawn_point + end + @spawn_points_pointer = 0 + end + + def spawn_point + @spawn_points[(@spawn_points_pointer += 1) % @spawn_points.size] + end + + def can_move_to?(x, y) + tile = tile_at(x, y) + tile && tile != @water + end + + def movement_penalty(x, y) + tile = tile_at(x, y) + case tile + when @sand + 0.33 + else + 0 + end + end + + def draw(viewport) + viewport = viewport.map { |p| p / TILE_SIZE } + x0, x1, y0, y1 = viewport.map(&:to_i) + (x0-1..x1).each do |x| + (y0-1..y1).each do |y| + row = @map[x] + map_x = x * TILE_SIZE + map_y = y * TILE_SIZE + if row + tile = @map[x][y] + if tile + tile.draw(map_x, map_y, 0) + else + @water.draw(map_x, map_y, 0) + end + else + @water.draw(map_x, map_y, 0) + end + end + end + end + + private + + def tile_at(x, y) + t_x = ((x / TILE_SIZE) % TILE_SIZE).floor + t_y = ((y / TILE_SIZE) % TILE_SIZE).floor + row = @map[t_x] + row ? row[t_y] : @water + end + + def load_tiles + tiles = Gosu::Image.load_tiles( + $window, Utils.media_path('ground.png'), + 128, 128, true) + @sand = tiles[0] + @grass = tiles[8] + @water = Gosu::Image.new( + Utils.media_path('water.png'), tileable: true) + end + + def generate_map + noises = Perlin::Noise.new(2) + contrast = Perlin::Curve.contrast( + Perlin::Curve::CUBIC, 2) + map = {} + MAP_WIDTH.times do |x| + map[x] = {} + MAP_HEIGHT.times do |y| + n = noises[x * 0.1, y * 0.1] + n = contrast.call(n) + map[x][y] = choose_tile(n) + end + end + map + end + + def generate_trees + noises = Perlin::Noise.new(2) + contrast = Perlin::Curve.contrast( + Perlin::Curve::CUBIC, 2) + trees = 0 + target_trees = rand(1500..1500) + while trees < target_trees do + x = rand(0..MAP_WIDTH * TILE_SIZE) + y = rand(0..MAP_HEIGHT * TILE_SIZE) + n = noises[x * 0.001, y * 0.001] + n = contrast.call(n) + if tile_at(x, y) == @grass && n > 0.5 + Tree.new(@object_pool, x, y, n * 2 - 1) + trees += 1 + end + end + end + + def generate_boxes + boxes = 0 + target_boxes = rand(50..200) + while boxes < target_boxes do + x = rand(0..MAP_WIDTH * TILE_SIZE) + y = rand(0..MAP_HEIGHT * TILE_SIZE) + if tile_at(x, y) != @water + Box.new(@object_pool, x, y) + boxes += 1 + end + end + end + + def generate_powerups + pups = 0 + target_pups = rand(20..30) + while pups < target_pups do + x = rand(0..MAP_WIDTH * TILE_SIZE) + y = rand(0..MAP_HEIGHT * TILE_SIZE) + if tile_at(x, y) != @water && + @object_pool.nearby_point(x, y, 150).empty? + random_powerup.new(@object_pool, x, y) + pups += 1 + end + end + end + + def random_powerup + [HealthPowerup, + RepairPowerup, + FireRatePowerup, + TankSpeedPowerup].sample + end + + def choose_tile(val) + case val + when 0.0..0.3 # 30% chance + @water + when 0.3..0.5 # 20% chance, water edges + @sand + else # 50% chance + @grass + end + end + + private + + def find_spawn_point + while true + x = rand(0..MAP_WIDTH * TILE_SIZE) + y = rand(0..MAP_HEIGHT * TILE_SIZE) + if can_move_to?(x, y) && + @object_pool.nearby_point(x, y, 150).empty? + return [x, y] + end + end + end + +end diff --git a/Games/Debris_Dodge/lib/entities/object_pool.rb b/Games/Debris_Dodge/lib/entities/object_pool.rb new file mode 100644 index 0000000000..016a7db96b --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/object_pool.rb @@ -0,0 +1,59 @@ +class ObjectPool + attr_accessor :map, :camera, :objects, :powerup_respawn_queue + + def size + @objects.size + end + + def initialize(box) + @tree = QuadTree.new(box) + @powerup_respawn_queue = PowerupRespawnQueue.new + @objects = [] + end + + def add(object) + @objects << object + @tree.insert(object) + end + + def tree_remove(object) + @tree.remove(object) + end + + def tree_insert(object) + @tree.insert(object) + end + + def update_all + @objects.each(&:update) + @objects.reject! do |o| + if o.removable? + @tree.remove(o) + true + end + end + @powerup_respawn_queue.respawn(self) + end + + def nearby_point(cx, cy, max_distance, object = nil) + hx, hy = cx + max_distance, cy + max_distance + # Fast, rough results + results = @tree.query_range( + AxisAlignedBoundingBox.new([cx, cy], [hx, hy])) + # Sift through to select fine-grained results + results.select do |o| + o != object && + Utils.distance_between( + o.x, o.y, cx, cy) <= max_distance + end + end + + def nearby(object, max_distance) + cx, cy = object.location + nearby_point(cx, cy, max_distance, object) + end + + def query_range(box) + @tree.query_range(box) + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/fire_rate_powerup.rb b/Games/Debris_Dodge/lib/entities/powerups/fire_rate_powerup.rb new file mode 100644 index 0000000000..76cadb4d50 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/fire_rate_powerup.rb @@ -0,0 +1,14 @@ +class FireRatePowerup < Powerup + def pickup(object) + if object.class == Tank + if object.fire_rate_modifier < 2 + object.fire_rate_modifier += 0.25 + end + true + end + end + + def graphics + :straight_gun + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/health_powerup.rb b/Games/Debris_Dodge/lib/entities/powerups/health_powerup.rb new file mode 100644 index 0000000000..c73cdbe9c3 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/health_powerup.rb @@ -0,0 +1,12 @@ +class HealthPowerup < Powerup + def pickup(object) + if object.class == Tank + object.health.increase(25) + true + end + end + + def graphics + :life_up + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/powerup.rb b/Games/Debris_Dodge/lib/entities/powerups/powerup.rb new file mode 100644 index 0000000000..edd2305ff7 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/powerup.rb @@ -0,0 +1,35 @@ +class Powerup < GameObject + def initialize(object_pool, x, y) + super + PowerupGraphics.new(self, graphics) + end + + def box + [x - 8, y - 8, + x + 8, y - 8, + x + 8, y + 8, + x - 8, y + 8] + end + + def on_collision(object) + if pickup(object) + PowerupSounds.play(object, object_pool.camera) + remove + end + end + + def pickup(object) + # override and implement application + end + + def remove + object_pool.powerup_respawn_queue.enqueue( + respawn_delay, + self.class, x, y) + mark_for_removal + end + + def respawn_delay + 30 + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/powerup_respawn_queue.rb b/Games/Debris_Dodge/lib/entities/powerups/powerup_respawn_queue.rb new file mode 100644 index 0000000000..b8f89d6691 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/powerup_respawn_queue.rb @@ -0,0 +1,23 @@ +class PowerupRespawnQueue + RESPAWN_DELAY = 1000 + def initialize + @respawn_queue = {} + @last_respawn = Gosu.milliseconds + end + + def enqueue(delay_seconds, type, x, y) + respawn_at = Gosu.milliseconds + delay_seconds * 1000 + @respawn_queue[respawn_at.to_i] = [type, x, y] + end + + def respawn(object_pool) + now = Gosu.milliseconds + return if now - @last_respawn < RESPAWN_DELAY + @respawn_queue.keys.each do |k| + next if k > now # not yet + type, x, y = @respawn_queue.delete(k) + type.new(object_pool, x, y) + end + @last_respawn = now + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/repair_powerup.rb b/Games/Debris_Dodge/lib/entities/powerups/repair_powerup.rb new file mode 100644 index 0000000000..fc3136d8f7 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/repair_powerup.rb @@ -0,0 +1,14 @@ +class RepairPowerup < Powerup + def pickup(object) + if object.class == Tank + if object.health.health < 100 + object.health.restore + end + true + end + end + + def graphics + :repair + end +end diff --git a/Games/Debris_Dodge/lib/entities/powerups/tank_speed_powerup.rb b/Games/Debris_Dodge/lib/entities/powerups/tank_speed_powerup.rb new file mode 100644 index 0000000000..c3e2f917f6 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/powerups/tank_speed_powerup.rb @@ -0,0 +1,14 @@ +class TankSpeedPowerup < Powerup + def pickup(object) + if object.class == Tank + if object.speed_modifier < 1.5 + object.speed_modifier += 0.10 + end + true + end + end + + def graphics + :wingman + end +end diff --git a/Games/Debris_Dodge/lib/entities/radar.rb b/Games/Debris_Dodge/lib/entities/radar.rb new file mode 100644 index 0000000000..96d7018a10 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/radar.rb @@ -0,0 +1,62 @@ +class Radar + UPDATE_FREQUENCY = 1000 + WIDTH = 150 + HEIGHT = 100 + PADDING = 10 + # Black with 33% transparency + BACKGROUND = Gosu::Color.new(255 * 0.33, 0, 0, 0) + attr_accessor :target + + def initialize(object_pool, target) + @object_pool = object_pool + @target = target + @last_update = 0 + end + + def update + if Gosu.milliseconds - @last_update > UPDATE_FREQUENCY + @nearby = nil + end + @nearby ||= @object_pool.nearby(@target, 2000).select do |o| + o.class == Tank && !o.health.dead? + end + end + + def draw + x1, x2, y1, y2 = radar_coords + $window.draw_quad( + x1, y1, BACKGROUND, + x2, y1, BACKGROUND, + x2, y2, BACKGROUND, + x1, y2, BACKGROUND, + 200) + draw_tank(@target, Gosu::Color::GREEN) + @nearby && @nearby.each do |t| + draw_tank(t, Gosu::Color::RED) + end + end + + private + + def draw_tank(tank, color) + x1, x2, y1, y2 = radar_coords + tx = x1 + WIDTH / 2 + (tank.x - @target.x) / 20 + ty = y1 + HEIGHT / 2 + (tank.y - @target.y) / 20 + if (x1..x2).include?(tx) && (y1..y2).include?(ty) + $window.draw_quad( + tx - 2, ty - 2, color, + tx + 2, ty - 2, color, + tx + 2, ty + 2, color, + tx - 2, ty + 2, color, + 300) + end + end + + def radar_coords + x1 = $window.width - WIDTH - PADDING + x2 = $window.width - PADDING + y1 = $window.height - HEIGHT - PADDING + y2 = $window.height - PADDING + [x1, x2, y1, y2] + end +end diff --git a/Games/Debris_Dodge/lib/entities/score_display.rb b/Games/Debris_Dodge/lib/entities/score_display.rb new file mode 100644 index 0000000000..cca560d0f6 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/score_display.rb @@ -0,0 +1,35 @@ +class ScoreDisplay + def initialize(object_pool, font_size=30) + @font_size = font_size + tanks = object_pool.objects.select do |o| + o.class == Tank + end + stats = tanks.map(&:input).map(&:stats) + stats.sort! do |stat1, stat2| + stat2.kills <=> stat1.kills + end + create_stats_image(stats) + end + + def create_stats_image(stats) + text = stats.map do |stat| + "#{stat.kills}: #{stat.name} " + end.join("\n") + @stats_image = Gosu::Image.from_text( + $window, text, Utils.main_font, @font_size) + end + + def draw + @stats_image.draw( + $window.width / 2 - @stats_image.width / 2, + $window.height / 4 + 30, + 1000) + end + + def draw_top_right + @stats_image.draw( + $window.width - @stats_image.width - 20, + 20, + 1000) + end +end diff --git a/Games/Debris_Dodge/lib/entities/tank.rb b/Games/Debris_Dodge/lib/entities/tank.rb new file mode 100644 index 0000000000..3e0fbf685b --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/tank.rb @@ -0,0 +1,64 @@ +class Tank < GameObject + SHOOT_DELAY = 500 + attr_accessor :throttle_down, :direction, + :gun_angle, :sounds, :physics, :graphics, :health, :input, + :fire_rate_modifier, :speed_modifier + + def initialize(object_pool, input) + x, y = object_pool.map.spawn_point + super(object_pool, x, y) + @input = input + @input.control(self) + @physics = TankPhysics.new(self, object_pool) + @sounds = TankSounds.new(self, object_pool) + @health = TankHealth.new(self, object_pool) + @graphics = TankGraphics.new(self) + @direction = rand(0..7) * 45 + @gun_angle = rand(0..360) + reset_modifiers + end + + def box + @physics.box + end + + def on_collision(object) + return unless object + # Avoid recursion + if object.class == Tank + # Inform AI about hit + object.input.on_collision(object) + else + # Call only on non-tanks to avoid recursion + object.on_collision(self) + end + # Bullets should not slow Tanks down + if object.class != Bullet + @sounds.collide if @physics.speed > 1 + end + end + + def shoot(target_x, target_y) + if can_shoot? + @last_shot = Gosu.milliseconds + Bullet.new(object_pool, @x, @y, target_x, target_y).fire( + self, 1500) + input.stats.add_shot + end + end + + def can_shoot? + Gosu.milliseconds - (@last_shot || 0) > + (SHOOT_DELAY / @fire_rate_modifier) + end + + def reset_modifiers + @fire_rate_modifier = 1 + @speed_modifier = 1 + end + + def to_s + "Tank [#{@health.health}@#{@x}:#{@y}@#{@physics.speed.round(2)}px/tick]#{@input.stats}" + end + +end diff --git a/Games/Debris_Dodge/lib/entities/tree.rb b/Games/Debris_Dodge/lib/entities/tree.rb new file mode 100644 index 0000000000..07635300d1 --- /dev/null +++ b/Games/Debris_Dodge/lib/entities/tree.rb @@ -0,0 +1,18 @@ +class Tree < GameObject + attr_reader :health, :graphics + + def initialize(object_pool, x, y, seed) + super(object_pool, x, y) + @graphics = TreeGraphics.new(self, seed) + @health = Health.new(self, object_pool, 30, false) + @angle = rand(-15..15) + end + + def on_collision(object) + @graphics.shake(object.direction) + end + + def box + [@x, @y] + end +end diff --git a/Games/Debris_Dodge/lib/game_states/demo_state.rb b/Games/Debris_Dodge/lib/game_states/demo_state.rb new file mode 100644 index 0000000000..13b9587661 --- /dev/null +++ b/Games/Debris_Dodge/lib/game_states/demo_state.rb @@ -0,0 +1,49 @@ +class DemoState < PlayState + attr_accessor :tank + + def enter + # Prevent reactivating HUD + end + + def update + super + @score_display = ScoreDisplay.new( + object_pool, 20) + end + + def draw + super + @score_display.draw_top_right + end + + def button_down(id) + super + if id == Gosu::KbSpace + target_tank = @tanks.reject do |t| + t == @camera.target + end.sample + switch_to_tank(target_tank) + end + end + + private + + def create_tanks(amount) + @map.spawn_points(amount * 3) + @tanks = [] + amount.times do |i| + @tanks << Tank.new(@object_pool, AiInput.new( + @names.random, @object_pool)) + end + target_tank = @tanks.sample + @hud = HUD.new(@object_pool, target_tank) + @hud.active = false + switch_to_tank(target_tank) + end + + def switch_to_tank(tank) + @camera.target = tank + @hud.player = tank + self.tank = tank + end +end diff --git a/Games/Debris_Dodge/lib/game_states/game_state.rb b/Games/Debris_Dodge/lib/game_states/game_state.rb new file mode 100644 index 0000000000..bb6f83eee0 --- /dev/null +++ b/Games/Debris_Dodge/lib/game_states/game_state.rb @@ -0,0 +1,27 @@ +class GameState + + def self.switch(new_state) + $window.state && $window.state.leave + $window.state = new_state + new_state.enter + end + + def enter + end + + def leave + end + + def draw + end + + def update + end + + def needs_redraw? + true + end + + def button_down(id) + end +end diff --git a/Games/Debris_Dodge/lib/game_states/menu_state.rb b/Games/Debris_Dodge/lib/game_states/menu_state.rb new file mode 100644 index 0000000000..294e7d4c06 --- /dev/null +++ b/Games/Debris_Dodge/lib/game_states/menu_state.rb @@ -0,0 +1,62 @@ +require 'singleton' +class MenuState < GameState + include Singleton + attr_accessor :play_state + + def initialize + @message = Gosu::Image.from_text( + "Tank Island", + 60, + font: Utils.title_font + ) + end + + def enter + music.play(true) + music.volume = 1 + end + + def leave + music.volume = 0 + music.stop + end + + def music + @@music ||= Gosu::Song.new( + Utils.media_path('menu_music.ogg')) + end + + def update + text = "Q: Quit\nN: New Game\nD: Demo" + text << "\nC: Continue" if @play_state + @info = Gosu::Image.from_text( + text, + 30, options = {font: Utils.main_font}) + end + + def draw + @message.draw( + $window.width / 2 - @message.width / 2, + $window.height / 2 - @message.height / 2, + 10) + @info.draw( + $window.width / 2 - @info.width / 2, + $window.height / 2 - @info.height / 2 + 100, + 10) + end + + def button_down(id) + $window.close if id == Gosu::KbQ + if id == Gosu::KbC && @play_state + GameState.switch(@play_state) + end + if id == Gosu::KbN + @play_state = PlayState.new + GameState.switch(@play_state) + end + if id == Gosu::KbD + @play_state = DemoState.new + GameState.switch(@play_state) + end + end +end diff --git a/Games/Debris_Dodge/lib/game_states/pause_state.rb b/Games/Debris_Dodge/lib/game_states/pause_state.rb new file mode 100644 index 0000000000..8a8078792d --- /dev/null +++ b/Games/Debris_Dodge/lib/game_states/pause_state.rb @@ -0,0 +1,61 @@ +require 'singleton' +class PauseState < GameState + include Singleton + attr_accessor :play_state + + def initialize + @message = Gosu::Image.from_text( + $window, "Game Paused", + Utils.title_font, 60) + end + + def enter + music.play(true) + music.volume = 1 + @score_display = ScoreDisplay.new(@play_state.object_pool) + @mouse_coords = [$window.mouse_x, $window.mouse_y] + end + + def leave + music.volume = 0 + music.stop + $window.mouse_x, $window.mouse_y = @mouse_coords + end + + def music + @@music ||= Gosu::Song.new( + $window, Utils.media_path('menu_music.ogg')) + end + + def draw + @play_state.draw + @message.draw( + $window.width / 2 - @message.width / 2, + $window.height / 4 - @message.height - 50, + 1000) + info.draw( + $window.width / 2 - info.width / 2, + $window.height / 4 - info.height, + 1000) + @score_display.draw + end + + def info + @info ||= Gosu::Image.from_text( + $window, 'Q: Quit to Main Menu', + Utils.main_font, 30) + end + + def button_down(id) + if id == Gosu::KbQ + MenuState.instance.play_state = @play_state + GameState.switch(MenuState.instance) + end + if id == Gosu::KbC && @play_state + GameState.switch(@play_state) + end + if id == Gosu::KbEscape + GameState.switch(@play_state) + end + end +end diff --git a/Games/Debris_Dodge/lib/game_states/play_state.rb b/Games/Debris_Dodge/lib/game_states/play_state.rb new file mode 100644 index 0000000000..89100befe5 --- /dev/null +++ b/Games/Debris_Dodge/lib/game_states/play_state.rb @@ -0,0 +1,119 @@ +class PlayState < GameState + attr_accessor :update_interval, :object_pool, :tank + + def initialize + # http://www.paulandstorm.com/wha/clown-names/ + @names = Names.new( + Utils.media_path('names.txt')) + @object_pool = ObjectPool.new(Map.bounding_box) + @map = Map.new(@object_pool) + @camera = Camera.new + @object_pool.camera = @camera + create_tanks(7) + end + + def update + StereoSample.cleanup + @object_pool.update_all + @camera.update + @hud.update + update_caption + end + + def draw + cam_x = @camera.x + cam_y = @camera.y + off_x = $window.width / 2 - cam_x + off_y = $window.height / 2 - cam_y + viewport = @camera.viewport + x1, x2, y1, y2 = viewport + box = AxisAlignedBoundingBox.new( + [x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2], + [x1 - Map::TILE_SIZE, y1 - Map::TILE_SIZE]) + $window.translate(off_x, off_y) do + zoom = @camera.zoom + $window.scale(zoom, zoom, cam_x, cam_y) do + @map.draw(viewport) + @object_pool.query_range(box).map do |o| + o.draw(viewport) + end + end + end + @hud.draw + end + + def button_down(id) + if id == Gosu::KbEscape + pause = PauseState.instance + pause.play_state = self + GameState.switch(pause) + end + if id == Gosu::KbT + t = Tank.new(@object_pool, + AiInput.new(@names.random, @object_pool)) + t.move(*@camera.mouse_coords) + end + if id == Gosu::KbF1 + $debug = !$debug + end + if id == Gosu::KbF2 + toggle_profiling + end + if id == Gosu::KbR + @tank.mark_for_removal + @tank = Tank.new(@object_pool, + PlayerInput.new('Player', @camera, @object_pool)) + @camera.target = @tank + @hud.player = @tank + end + end + + def leave + StereoSample.stop_all + if @profiling_now + toggle_profiling + end + @hud.active = false + end + + def enter + @hud.active = true + end + + private + + def create_tanks(amount) + @map.spawn_points(amount * 3) + @tank = Tank.new(@object_pool, + PlayerInput.new('Player', @camera, @object_pool)) + amount.times do |i| + Tank.new(@object_pool, AiInput.new( + @names.random, @object_pool)) + end + @camera.target = @tank + @hud = HUD.new(@object_pool, @tank) + end + + def toggle_profiling + require 'ruby-prof' unless defined?(RubyProf) + if @profiling_now + result = RubyProf.stop + printer = RubyProf::FlatPrinter.new(result) + printer.print(STDOUT, min_percent: 0.01) + @profiling_now = false + else + RubyProf.start + @profiling_now = true + end + end + + def update_caption + now = Gosu.milliseconds + if now - (@caption_updated_at || 0) > 1000 + $window.caption = 'Tank Island. ' << + "[FPS: #{Gosu.fps}. " << + "Tank @ #{@tank.x.round}:#{@tank.y.round}]" + @caption_updated_at = now + end + end +end diff --git a/Games/Debris_Dodge/lib/misc/axis_aligned_bounding_box.rb b/Games/Debris_Dodge/lib/misc/axis_aligned_bounding_box.rb new file mode 100644 index 0000000000..70bc9e30d1 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/axis_aligned_bounding_box.rb @@ -0,0 +1,33 @@ +class AxisAlignedBoundingBox + attr_reader :center, :half_dimension + def initialize(center, half_dimension) + @center = center + @half_dimension = half_dimension + @dhx = (@half_dimension[0] - @center[0]).abs + @dhy = (@half_dimension[1] - @center[1]).abs + end + + def contains?(point) + return false unless (@center[0] + @dhx) >= point[0] + return false unless (@center[0] - @dhx) <= point[0] + return false unless (@center[1] + @dhy) >= point[1] + return false unless (@center[1] - @dhy) <= point[1] + true + end + + def intersects?(other) + ocx, ocy = other.center + ohx, ohy = other.half_dimension + odhx = (ohx - ocx).abs + return false unless (@center[0] + @dhx) >= (ocx - odhx) + return false unless (@center[0] - @dhx) <= (ocx + odhx) + odhy = (ohy - ocy).abs + return false unless (@center[1] + @dhy) >= (ocy - odhy) + return false unless (@center[1] - @dhy) <= (ocy + odhy) + true + end + + def to_s + "c: #{@center}, h: #{@half_dimension}" + end +end diff --git a/Games/Debris_Dodge/lib/misc/game_window.rb b/Games/Debris_Dodge/lib/misc/game_window.rb new file mode 100644 index 0000000000..504061cf4a --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/game_window.rb @@ -0,0 +1,30 @@ +class GameWindow < Gosu::Window + attr_accessor :state + + def initialize + super((ENV['w'] || 800).to_i, + (ENV['h'] || 600).to_i, + (ENV['fs'] ? true : false)) + end + + def update + Utils.track_update_interval + @state.update + end + + def draw + @state.draw + end + + def needs_redraw? + @state.needs_redraw? + end + + def needs_cursor? + Utils.update_interval > 200 + end + + def button_down(id) + @state.button_down(id) + end +end diff --git a/Games/Debris_Dodge/lib/misc/names.rb b/Games/Debris_Dodge/lib/misc/names.rb new file mode 100644 index 0000000000..09d2825521 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/names.rb @@ -0,0 +1,13 @@ +class Names + def initialize(file) + @names = File.read(file).split("\n").reject do |n| + n.size > 12 + end + end + + def random + name = @names.sample + @names.delete(name) + name + end +end diff --git a/Games/Debris_Dodge/lib/misc/quad_tree.rb b/Games/Debris_Dodge/lib/misc/quad_tree.rb new file mode 100644 index 0000000000..6a119aee01 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/quad_tree.rb @@ -0,0 +1,91 @@ +class QuadTree + NODE_CAPACITY = 12 + attr_accessor :ne, :nw, :se, :sw, :objects + + def initialize(boundary) + @boundary = boundary + @objects = [] + end + + def insert(game_object) + return false unless @boundary.contains?( + game_object.location) + + if @objects.size < NODE_CAPACITY + @objects << game_object + return true + end + + subdivide unless @nw + + return true if @nw.insert(game_object) + return true if @ne.insert(game_object) + return true if @sw.insert(game_object) + return true if @se.insert(game_object) + + # should never happen + raise "Failed to insert #{game_object}" + end + + def remove(game_object) + return false unless @boundary.contains?( + game_object.location) + if @objects.delete(game_object) + return true + end + return false unless @nw + return true if @nw.remove(game_object) + return true if @ne.remove(game_object) + return true if @sw.remove(game_object) + return true if @se.remove(game_object) + false + end + + def query_range(range) + result = [] + unless @boundary.intersects?(range) + return result + end + + @objects.each do |o| + if range.contains?(o.location) + result << o + end + end + + # Not subdivided + return result unless @ne + + result += @nw.query_range(range) + result += @ne.query_range(range) + result += @sw.query_range(range) + result += @se.query_range(range) + + result + end + + private + + def subdivide + cx, cy = @boundary.center + hx, hy = @boundary.half_dimension + hhx = (cx - hx).abs / 2.0 + hhy = (cy - hy).abs / 2.0 + @nw = QuadTree.new( + AxisAlignedBoundingBox.new( + [cx - hhx, cy - hhy], + [cx, cy])) + @ne = QuadTree.new( + AxisAlignedBoundingBox.new( + [cx + hhx, cy - hhy], + [cx, cy])) + @sw = QuadTree.new( + AxisAlignedBoundingBox.new( + [cx - hhx, cy + hhy], + [cx, cy])) + @se = QuadTree.new( + AxisAlignedBoundingBox.new( + [cx + hhx, cy + hhy], + [cx, cy])) + end +end diff --git a/Games/Debris_Dodge/lib/misc/stats.rb b/Games/Debris_Dodge/lib/misc/stats.rb new file mode 100644 index 0000000000..394b584991 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/stats.rb @@ -0,0 +1,55 @@ +class Stats + attr_reader :name, :kills, :deaths, :shots, :changed_at + def initialize(name) + @name = name + @kills = @deaths = @shots = @damage = @damage_dealt = 0 + changed + end + + def add_kill(amount = 1) + @kills += amount + changed + end + + def add_death + @deaths += 1 + changed + end + + def add_shot + @shots += 1 + changed + end + + def add_damage(amount) + @damage += amount + changed + end + + def damage + @damage.round + end + + def add_damage_dealt(amount) + @damage_dealt += amount + changed + end + + def damage_dealt + @damage_dealt.round + end + + def to_s + "[kills: #{@kills}, " \ + "deaths: #{@deaths}, " \ + "shots: #{@shots}, " \ + "damage: #{damage}, " \ + "damage_dealt: #{damage_dealt}]" + end + + private + + def changed + @changed_at = Gosu.milliseconds + end +end diff --git a/Games/Debris_Dodge/lib/misc/stereo_sample.rb b/Games/Debris_Dodge/lib/misc/stereo_sample.rb new file mode 100644 index 0000000000..211f6ca2f0 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/stereo_sample.rb @@ -0,0 +1,96 @@ +class StereoSample + MAX_POLIPHONY = 16 + @@all_instances = [] + + def self.register_instances(instances) + @@all_instances << instances + end + + def self.cleanup + @@all_instances.each do |instances| + instances.each do |key, instance| + unless instance.playing? || instance.paused? + instances.delete(key) + end + end + end + end + + def self.stop_all + @@all_instances.each do |instances| + instances.each do |key, instance| + if instance.playing? + instance.stop + end + end + end + end + + def initialize(window, sound_l, sound_r = sound_l) + @sound_l = Gosu::Sample.new(sound_l) + # Use same sample in mono -> stereo + if sound_l == sound_r + @sound_r = @sound_l + else + @sound_r = Gosu::Sample.new(sound_r) + end + @instances = {} + self.class.register_instances(@instances) + end + + def paused?(id = :default) + i = @instances["#{id}_l"] + i && i.paused? + end + + def playing?(id = :default) + i = @instances["#{id}_l"] + i && i.playing? + end + + def stopped?(id = :default) + @instances["#{id}_l"].nil? + end + + def play(id = :default, pan = 0, + volume = 1, speed = 1, looping = false) + if @instances.size > MAX_POLIPHONY + return + end + @instances["#{id}_l"] = @sound_l.play_pan( + -0.2, 0, speed, looping) + @instances["#{id}_r"] = @sound_r.play_pan( + 0.2, 0, speed, looping) + volume_and_pan(id, volume, pan) + end + + def pause(id = :default) + @instances["#{id}_l"].pause + @instances["#{id}_r"].pause + end + + def resume(id = :default) + @instances["#{id}_l"].resume + @instances["#{id}_r"].resume + end + + def stop + @instances.delete("#{id}_l").stop + @instances.delete("#{id}_r").stop + end + + def volume_and_pan(id, volume, pan) + return unless @instances["#{id}_l"] + if pan > 0 + pan_l = 1 - pan * 2 + pan_r = 1 + else + pan_l = 1 + pan_r = 1 + pan * 2 + end + pan_l *= volume + pan_r *= volume + @instances["#{id}_l"].volume = [pan_l, 0.05].max + @instances["#{id}_r"].volume = [pan_r, 0.05].max + end +end diff --git a/Games/Debris_Dodge/lib/misc/utils.rb b/Games/Debris_Dodge/lib/misc/utils.rb new file mode 100644 index 0000000000..88800da504 --- /dev/null +++ b/Games/Debris_Dodge/lib/misc/utils.rb @@ -0,0 +1,145 @@ +module Utils + HEARING_DISTANCE = 1000.0 + DEBUG_COLORS = [ + Gosu::Color::RED, + Gosu::Color::BLUE, + Gosu::Color::YELLOW, + Gosu::Color::WHITE + ] + def self.media_path(file) + File.join(File.dirname(File.dirname(File.dirname( + __FILE__))), 'media', file) + end + + def self.track_update_interval + now = Gosu.milliseconds + @update_interval = (now - (@last_update ||= 0)).to_f + @last_update = now + end + + def self.title_font + media_path('top_secret.ttf') + end + + def self.main_font + media_path('armalite_rifle.ttf') + end + + def self.update_interval + @update_interval ||= $window.update_interval + end + + def self.adjust_speed(speed) + speed * update_interval / 33.33 + end + + def self.button_down?(button) + @buttons ||= {} + now = Gosu.milliseconds + now = now - (now % 150) + if $window.button_down?(button) + @buttons[button] = now + true + elsif @buttons[button] + if now == @buttons[button] + true + else + @buttons.delete(button) + false + end + end + end + + def self.rotate(angle, around_x, around_y, *points) + result = [] + angle = angle * Math::PI / 180.0 + points.each_slice(2) do |x, y| + r_x = Math.cos(angle) * (around_x - x) - + Math.sin(angle) * (around_y - y) + around_x + r_y = Math.sin(angle) * (around_x - x) + + Math.cos(angle) * (around_y - y) + around_y + result << r_x + result << r_y + end + result + end + + # http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + def self.point_in_poly(testx, testy, *poly) + nvert = poly.size / 2 # Number of vertices in poly + vertx = [] + verty = [] + poly.each_slice(2) do |x, y| + vertx << x + verty << y + end + inside = false + j = nvert - 1 + (0..nvert - 1).each do |i| + if (((verty[i] > testy) != (verty[j] > testy)) && + (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / + (verty[j] - verty[i]) + vertx[i])) + inside = !inside + end + j = i + end + inside + end + + def self.distance_between(x1, y1, x2, y2) + dx = x1 - x2 + dy = y1 - y2 + Math.sqrt(dx * dx + dy * dy) + end + + def self.angle_between(x, y, target_x, target_y) + dx = target_x - x + dy = target_y - y + (180 - Math.atan2(dx, dy) * 180 / Math::PI) + 360 % 360 + end + + def self.point_at_distance(source_x, source_y, angle, distance) + angle = (90 - angle) * Math::PI / 180 + x = source_x + Math.cos(angle) * distance + y = source_y - Math.sin(angle) * distance + [x, y] + end + + def self.mark_corners(box) + i = 0 + box.each_slice(2) do |x, y| + color = DEBUG_COLORS[i] + $window.draw_triangle( + x - 3, y - 3, color, + x, y, color, + x + 3, y - 3, color, + 100) + i = (i + 1) % 4 + end + end + + def self.volume(object, camera) + return 1 if object == camera.target + distance = Utils.distance_between( + camera.target.x, camera.target.y, + object.x, object.y) + distance = [(HEARING_DISTANCE - distance), 0].max + distance / HEARING_DISTANCE + end + + def self.pan(object, camera) + return 0 if object == camera.target + pan = object.x - camera.target.x + sig = pan > 0 ? 1 : -1 + pan = (pan % HEARING_DISTANCE) / HEARING_DISTANCE + if sig > 0 + pan + else + -1 + pan + end + end + + def self.volume_and_pan(object, camera) + [volume(object, camera), pan(object, camera)] + end +end diff --git a/Games/Debris_Dodge/media/armalite_rifle.ttf b/Games/Debris_Dodge/media/armalite_rifle.ttf new file mode 100644 index 0000000000..06619a3aef Binary files /dev/null and b/Games/Debris_Dodge/media/armalite_rifle.ttf differ diff --git a/Games/Debris_Dodge/media/boxes_barrels.json b/Games/Debris_Dodge/media/boxes_barrels.json new file mode 100644 index 0000000000..f74563a202 --- /dev/null +++ b/Games/Debris_Dodge/media/boxes_barrels.json @@ -0,0 +1,60 @@ +{"frames": { + +"barrel_side.png": +{ + "frame": {"x":2,"y":2,"w":30,"h":36}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":36}, + "sourceSize": {"w":30,"h":36} +}, +"barrel_top.png": +{ + "frame": {"x":34,"y":2,"w":30,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":32}, + "sourceSize": {"w":30,"h":32} +}, +"box.png": +{ + "frame": {"x":42,"y":40,"w":50,"h":50}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":50,"h":50}, + "sourceSize": {"w":50,"h":50} +}, +"box_2x1.png": +{ + "frame": {"x":2,"y":176,"w":80,"h":53}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":80,"h":53}, + "sourceSize": {"w":80,"h":53} +}, +"box_2x2.png": +{ + "frame": {"x":2,"y":92,"w":80,"h":82}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":80,"h":82}, + "sourceSize": {"w":80,"h":82} +}, +"box_small.png": +{ + "frame": {"x":2,"y":40,"w":38,"h":40}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":38,"h":40}, + "sourceSize": {"w":38,"h":40} +}}, +"meta": { + "app": "http://www.codeandweb.com/texturepacker ", + "version": "1.0", + "image": "boxes_barrels.png", + "format": "RGBA8888", + "size": {"w":94,"h":231}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:e1f8dd3e75d56379964832e4e1fe08fd:ca59b503f7b878a09d84d41cbeb53a15:d01cf1bf6125b2a1524959777ff4451f$" +} +} diff --git a/Games/Debris_Dodge/media/boxes_barrels.png b/Games/Debris_Dodge/media/boxes_barrels.png new file mode 100644 index 0000000000..89a94f1286 Binary files /dev/null and b/Games/Debris_Dodge/media/boxes_barrels.png differ diff --git a/Games/Debris_Dodge/media/bullet.png b/Games/Debris_Dodge/media/bullet.png new file mode 100644 index 0000000000..a8016083e9 Binary files /dev/null and b/Games/Debris_Dodge/media/bullet.png differ diff --git a/Games/Debris_Dodge/media/c_dot.png b/Games/Debris_Dodge/media/c_dot.png new file mode 100644 index 0000000000..c848f78c53 Binary files /dev/null and b/Games/Debris_Dodge/media/c_dot.png differ diff --git a/Games/Debris_Dodge/media/country_field.png b/Games/Debris_Dodge/media/country_field.png new file mode 100644 index 0000000000..4a2dffdb18 Binary files /dev/null and b/Games/Debris_Dodge/media/country_field.png differ diff --git a/Games/Debris_Dodge/media/crash.ogg b/Games/Debris_Dodge/media/crash.ogg new file mode 100644 index 0000000000..8a9bd8cd39 Binary files /dev/null and b/Games/Debris_Dodge/media/crash.ogg differ diff --git a/Games/Debris_Dodge/media/damage1.png b/Games/Debris_Dodge/media/damage1.png new file mode 100644 index 0000000000..371c304e66 Binary files /dev/null and b/Games/Debris_Dodge/media/damage1.png differ diff --git a/Games/Debris_Dodge/media/damage2.png b/Games/Debris_Dodge/media/damage2.png new file mode 100644 index 0000000000..5ca6de4f34 Binary files /dev/null and b/Games/Debris_Dodge/media/damage2.png differ diff --git a/Games/Debris_Dodge/media/damage3.png b/Games/Debris_Dodge/media/damage3.png new file mode 100644 index 0000000000..b676c0df70 Binary files /dev/null and b/Games/Debris_Dodge/media/damage3.png differ diff --git a/Games/Debris_Dodge/media/damage4.png b/Games/Debris_Dodge/media/damage4.png new file mode 100644 index 0000000000..b748883b92 Binary files /dev/null and b/Games/Debris_Dodge/media/damage4.png differ diff --git a/Games/Debris_Dodge/media/decor.json b/Games/Debris_Dodge/media/decor.json new file mode 100644 index 0000000000..e5a59aaee4 --- /dev/null +++ b/Games/Debris_Dodge/media/decor.json @@ -0,0 +1,516 @@ +{"frames": { + +"aircraft_1d_destroyed.png": +{ + "frame": {"x":451,"y":102,"w":57,"h":42}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":57,"h":42}, + "sourceSize": {"w":57,"h":42} +}, +"aircraft_2d_destroyed.png": +{ + "frame": {"x":2,"y":680,"w":63,"h":47}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":63,"h":47}, + "sourceSize": {"w":63,"h":47} +}, +"aircraft_3d_destroyed.png": +{ + "frame": {"x":368,"y":125,"w":81,"h":55}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":81,"h":55}, + "sourceSize": {"w":81,"h":55} +}, +"aircraft_3e_destroyed.png": +{ + "frame": {"x":368,"y":68,"w":81,"h":55}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":81,"h":55}, + "sourceSize": {"w":81,"h":55} +}, +"barrels_1.png": +{ + "frame": {"x":430,"y":738,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"barrels_2.png": +{ + "frame": {"x":364,"y":680,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"bush_1.png": +{ + "frame": {"x":102,"y":820,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"bush_big.png": +{ + "frame": {"x":368,"y":182,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"crates_1.png": +{ + "frame": {"x":168,"y":794,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"crates_2.png": +{ + "frame": {"x":102,"y":754,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"crates_3.png": +{ + "frame": {"x":331,"y":812,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"crates_4.png": +{ + "frame": {"x":265,"y":760,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"dirt_001.png": +{ + "frame": {"x":2,"y":480,"w":88,"h":68}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":88,"h":68}, + "sourceSize": {"w":88,"h":68} +}, +"dirt_002.png": +{ + "frame": {"x":2,"y":550,"w":88,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":88,"h":64}, + "sourceSize": {"w":88,"h":64} +}, +"dirt_grass_hor_01.png": +{ + "frame": {"x":2,"y":272,"w":128,"h":104}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":104}, + "sourceSize": {"w":128,"h":104} +}, +"dirt_grass_hor_02.png": +{ + "frame": {"x":2,"y":166,"w":128,"h":104}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":104}, + "sourceSize": {"w":128,"h":104} +}, +"dirt_grass_vert.png": +{ + "frame": {"x":132,"y":36,"w":104,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":104,"h":128}, + "sourceSize": {"w":104,"h":128} +}, +"dirt_road_hor.png": +{ + "frame": {"x":2,"y":2,"w":256,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":256,"h":32}, + "sourceSize": {"w":256,"h":32} +}, +"dirt_road_vert.png": +{ + "frame": {"x":2,"y":738,"w":32,"h":256}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":256}, + "sourceSize": {"w":32,"h":256} +}, +"grass_01.png": +{ + "frame": {"x":238,"y":68,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"grass_02.png": +{ + "frame": {"x":2,"y":36,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"road_1.png": +{ + "frame": {"x":234,"y":532,"w":64,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":128}, + "sourceSize": {"w":64,"h":128} +}, +"road_2.png": +{ + "frame": {"x":430,"y":608,"w":64,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":128}, + "sourceSize": {"w":64,"h":128} +}, +"road_3.png": +{ + "frame": {"x":364,"y":486,"w":64,"h":192}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":192}, + "sourceSize": {"w":64,"h":192} +}, +"road_4.png": +{ + "frame": {"x":432,"y":414,"w":64,"h":192}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":192}, + "sourceSize": {"w":64,"h":192} +}, +"road_5.png": +{ + "frame": {"x":260,"y":2,"w":192,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":64}, + "sourceSize": {"w":192,"h":64} +}, +"road_asphalt_clean_hor.png": +{ + "frame": {"x":364,"y":312,"w":128,"h":100}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":100}, + "sourceSize": {"w":128,"h":100} +}, +"road_asphalt_clean_to_damaged_hor.png": +{ + "frame": {"x":234,"y":300,"w":128,"h":100}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":100}, + "sourceSize": {"w":128,"h":100} +}, +"road_asphalt_clean_to_damaged_vert.png": +{ + "frame": {"x":132,"y":426,"w":100,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":100,"h":128}, + "sourceSize": {"w":100,"h":128} +}, +"road_asphalt_clean_vert.png": +{ + "frame": {"x":234,"y":402,"w":100,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":100,"h":128}, + "sourceSize": {"w":100,"h":128} +}, +"road_asphalt_damaged_hor.png": +{ + "frame": {"x":2,"y":378,"w":128,"h":100}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":100}, + "sourceSize": {"w":128,"h":100} +}, +"road_asphalt_damaged_to_clean_hor.png": +{ + "frame": {"x":234,"y":198,"w":128,"h":100}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":100}, + "sourceSize": {"w":128,"h":100} +}, +"road_asphalt_damaged_to_clean_vert.png": +{ + "frame": {"x":132,"y":296,"w":100,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":100,"h":128}, + "sourceSize": {"w":100,"h":128} +}, +"road_asphalt_damaged_vert.png": +{ + "frame": {"x":132,"y":166,"w":100,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":100,"h":128}, + "sourceSize": {"w":100,"h":128} +}, +"road_corner_1.png": +{ + "frame": {"x":199,"y":728,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"road_corner_2.png": +{ + "frame": {"x":133,"y":688,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"road_corner_3.png": +{ + "frame": {"x":67,"y":688,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"road_corner_4.png": +{ + "frame": {"x":36,"y":760,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_010.png": +{ + "frame": {"x":364,"y":414,"w":66,"h":70}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":70}, + "sourceSize": {"w":66,"h":70} +}, +"rock_1.png": +{ + "frame": {"x":36,"y":936,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_2.png": +{ + "frame": {"x":36,"y":870,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_3.png": +{ + "frame": {"x":428,"y":804,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_4.png": +{ + "frame": {"x":362,"y":746,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_5.png": +{ + "frame": {"x":296,"y":694,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_6.png": +{ + "frame": {"x":230,"y":662,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_7.png": +{ + "frame": {"x":164,"y":622,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_8.png": +{ + "frame": {"x":98,"y":622,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"rock_9.png": +{ + "frame": {"x":128,"y":556,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"tank1_body_destroyed.png": +{ + "frame": {"x":92,"y":480,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1b_body_destroyed.png": +{ + "frame": {"x":92,"y":530,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank2_body_destroyed.png": +{ + "frame": {"x":454,"y":2,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_body_destroyed.png": +{ + "frame": {"x":454,"y":52,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank3_body_destroyed.png": +{ + "frame": {"x":336,"y":525,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3b_body_destroyed.png": +{ + "frame": {"x":336,"y":484,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3c_body_destroyed.png": +{ + "frame": {"x":336,"y":443,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3d_body_destroyed.png": +{ + "frame": {"x":336,"y":402,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"truck1_destroyed.png": +{ + "frame": {"x":2,"y":616,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1b_destroyed.png": +{ + "frame": {"x":332,"y":630,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1c_destroyed.png": +{ + "frame": {"x":300,"y":596,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_destroyed.png": +{ + "frame": {"x":332,"y":566,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2b_destroyed.png": +{ + "frame": {"x":300,"y":532,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2c_destroyed.png": +{ + "frame": {"x":66,"y":616,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_destroyed.png": +{ + "frame": {"x":34,"y":616,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}}, +"meta": { + "app": "http://www.texturepacker.com", + "version": "1.0", + "image": "decor.png", + "format": "RGBA8888", + "size": {"w":512,"h":1024}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:2e6b6964f24c7abfaa85a804e2dc1b05$" +} +} diff --git a/Games/Debris_Dodge/media/decor.png b/Games/Debris_Dodge/media/decor.png new file mode 100644 index 0000000000..9c385f8870 Binary files /dev/null and b/Games/Debris_Dodge/media/decor.png differ diff --git a/Games/Debris_Dodge/media/decor.psd b/Games/Debris_Dodge/media/decor.psd new file mode 100644 index 0000000000..ba2766e4d6 Binary files /dev/null and b/Games/Debris_Dodge/media/decor.psd differ diff --git a/Games/Debris_Dodge/media/explosion.ogg b/Games/Debris_Dodge/media/explosion.ogg new file mode 100644 index 0000000000..04d6799b97 Binary files /dev/null and b/Games/Debris_Dodge/media/explosion.ogg differ diff --git a/Games/Debris_Dodge/media/explosion.png b/Games/Debris_Dodge/media/explosion.png new file mode 100644 index 0000000000..42fa4425f9 Binary files /dev/null and b/Games/Debris_Dodge/media/explosion.png differ diff --git a/Games/Debris_Dodge/media/fire.ogg b/Games/Debris_Dodge/media/fire.ogg new file mode 100644 index 0000000000..0c82c760df Binary files /dev/null and b/Games/Debris_Dodge/media/fire.ogg differ diff --git a/Games/Debris_Dodge/media/ground.json b/Games/Debris_Dodge/media/ground.json new file mode 100644 index 0000000000..1193be2e7a --- /dev/null +++ b/Games/Debris_Dodge/media/ground.json @@ -0,0 +1,492 @@ +{"frames": { + +"beach_bl.png": +{ + "frame": {"x":896,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bl_grass.png": +{ + "frame": {"x":768,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_01.png": +{ + "frame": {"x":640,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_01_grass.png": +{ + "frame": {"x":640,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_02.png": +{ + "frame": {"x":640,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_02_grass.png": +{ + "frame": {"x":896,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_03.png": +{ + "frame": {"x":768,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_03_grass.png": +{ + "frame": {"x":640,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_04.png": +{ + "frame": {"x":512,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_04_grass.png": +{ + "frame": {"x":512,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_05.png": +{ + "frame": {"x":512,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_bm_05_grass.png": +{ + "frame": {"x":512,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_br.png": +{ + "frame": {"x":896,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_br_grass.png": +{ + "frame": {"x":768,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_l_up_diagonal.png": +{ + "frame": {"x":640,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_l_up_diagonal_grass.png": +{ + "frame": {"x":512,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_l_up_diagonal_neighbour.png": +{ + "frame": {"x":384,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_l_up_diagonal_neighbour_grass.png": +{ + "frame": {"x":384,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_01.png": +{ + "frame": {"x":384,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_01_grass.png": +{ + "frame": {"x":384,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_02.png": +{ + "frame": {"x":384,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_02_grass.png": +{ + "frame": {"x":896,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_03.png": +{ + "frame": {"x":768,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_03_grass.png": +{ + "frame": {"x":640,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_04.png": +{ + "frame": {"x":512,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_lm_04_grass.png": +{ + "frame": {"x":384,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_diagonal_neighbour.png": +{ + "frame": {"x":256,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_diagonal_neighbour_grass.png": +{ + "frame": {"x":256,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_down_diagonal.png": +{ + "frame": {"x":256,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_down_diagonal_grass.png": +{ + "frame": {"x":256,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_down_diagonal_neighbour.png": +{ + "frame": {"x":256,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_down_diagonal_neighbour_grass.png": +{ + "frame": {"x":256,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_up_diagonal.png": +{ + "frame": {"x":896,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_r_up_diagonal_grass.png": +{ + "frame": {"x":768,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_01-22.png": +{ + "frame": {"x":256,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_01.png": +{ + "frame": {"x":640,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_01_grass-22.png": +{ + "frame": {"x":384,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_01_grass.png": +{ + "frame": {"x":512,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_02.png": +{ + "frame": {"x":128,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_02_grass.png": +{ + "frame": {"x":128,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_03.png": +{ + "frame": {"x":128,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_03_grass.png": +{ + "frame": {"x":128,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_04.png": +{ + "frame": {"x":128,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_04_grass.png": +{ + "frame": {"x":128,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_05.png": +{ + "frame": {"x":128,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_rm_05_grass.png": +{ + "frame": {"x":896,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tl.png": +{ + "frame": {"x":768,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tl_grass.png": +{ + "frame": {"x":640,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_01.png": +{ + "frame": {"x":512,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_01_grass.png": +{ + "frame": {"x":384,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_02.png": +{ + "frame": {"x":256,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_02_grass.png": +{ + "frame": {"x":128,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_03.png": +{ + "frame": {"x":0,"y":896,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_03_grass.png": +{ + "frame": {"x":0,"y":768,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_04.png": +{ + "frame": {"x":0,"y":640,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tm_04_grass.png": +{ + "frame": {"x":0,"y":512,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tr.png": +{ + "frame": {"x":0,"y":384,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"beach_tr_grass.png": +{ + "frame": {"x":0,"y":256,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"grass.png": +{ + "frame": {"x":0,"y":128,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}, +"sand.png": +{ + "frame": {"x":0,"y":0,"w":128,"h":128}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, + "sourceSize": {"w":128,"h":128} +}}, +"meta": { + "app": "http://www.texturepacker.com", + "version": "1.0", + "image": "ground.png", + "format": "RGBA8888", + "size": {"w":1024,"h":1024}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:a4e7956c80b1dabce22dc97d34f9811b$" +} +} diff --git a/Games/Debris_Dodge/media/ground.png b/Games/Debris_Dodge/media/ground.png new file mode 100644 index 0000000000..536a5ceb08 Binary files /dev/null and b/Games/Debris_Dodge/media/ground.png differ diff --git a/Games/Debris_Dodge/media/ground_units.json b/Games/Debris_Dodge/media/ground_units.json new file mode 100644 index 0000000000..a3bcc73653 --- /dev/null +++ b/Games/Debris_Dodge/media/ground_units.json @@ -0,0 +1,900 @@ +{"frames": { + +"tank1_body.png": +{ + "frame": {"x":278,"y":338,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_body_1b.png": +{ + "frame": {"x":314,"y":382,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_body_destroyed.png": +{ + "frame": {"x":322,"y":332,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_body_destroyed_shadow.png": +{ + "frame": {"x":438,"y":346,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_body_hit.png": +{ + "frame": {"x":366,"y":302,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_body_shadow.png": +{ + "frame": {"x":402,"y":302,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1_dualgun.png": +{ + "frame": {"x":336,"y":244,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_dualgun_hit.png": +{ + "frame": {"x":234,"y":196,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_gun.png": +{ + "frame": {"x":176,"y":196,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_gun_destroyed-02.png": +{ + "frame": {"x":60,"y":196,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_gun_destroyed.png": +{ + "frame": {"x":118,"y":196,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_gun_hit.png": +{ + "frame": {"x":2,"y":196,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1_track.png": +{ + "frame": {"x":394,"y":352,"w":34,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":28}, + "sourceSize": {"w":34,"h":28} +}, +"tank1b_body.png": +{ + "frame": {"x":358,"y":352,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1b_body_destroyed.png": +{ + "frame": {"x":474,"y":346,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1b_body_destroyed_shadow.png": +{ + "frame": {"x":438,"y":346,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1b_body_shadow.png": +{ + "frame": {"x":402,"y":302,"w":34,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":48}, + "sourceSize": {"w":34,"h":48} +}, +"tank1b_dualgun.png": +{ + "frame": {"x":176,"y":254,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_dualgun_hit.png": +{ + "frame": {"x":118,"y":254,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_gun.png": +{ + "frame": {"x":60,"y":254,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_gun_destroyed-02.png": +{ + "frame": {"x":452,"y":288,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_gun_destroyed.png": +{ + "frame": {"x":2,"y":254,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_gun_hit.png": +{ + "frame": {"x":394,"y":244,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank1b_track.png": +{ + "frame": {"x":394,"y":382,"w":34,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":34,"h":28}, + "sourceSize": {"w":34,"h":28} +}, +"tank2_body.png": +{ + "frame": {"x":292,"y":138,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2_body_destroyed.png": +{ + "frame": {"x":458,"y":180,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2_body_destroyed_shadow.png": +{ + "frame": {"x":234,"y":254,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2_body_hit.png": +{ + "frame": {"x":458,"y":130,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2_body_shadow.png": +{ + "frame": {"x":292,"y":188,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2_dualgun.png": +{ + "frame": {"x":342,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_dualgun_destroyed.png": +{ + "frame": {"x":274,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_dualgun_hit.png": +{ + "frame": {"x":206,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_gun.png": +{ + "frame": {"x":138,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_gun_destroyed.png": +{ + "frame": {"x":70,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_gun_hit.png": +{ + "frame": {"x":2,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2_track.png": +{ + "frame": {"x":322,"y":302,"w":42,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":28}, + "sourceSize": {"w":42,"h":28} +}, +"tank2b_body.png": +{ + "frame": {"x":234,"y":304,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_body_destroyed.png": +{ + "frame": {"x":278,"y":288,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_body_destroyed_shadow.png": +{ + "frame": {"x":234,"y":254,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_body_hit.png": +{ + "frame": {"x":292,"y":238,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_body_shadow.png": +{ + "frame": {"x":292,"y":188,"w":42,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":48}, + "sourceSize": {"w":42,"h":48} +}, +"tank2b_dualgun.png": +{ + "frame": {"x":274,"y":70,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2b_dualgun_destroyed.png": +{ + "frame": {"x":206,"y":70,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2b_dualgun_hit.png": +{ + "frame": {"x":138,"y":70,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2b_gun.png": +{ + "frame": {"x":70,"y":70,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2b_gun_destroyed.png": +{ + "frame": {"x":2,"y":70,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank2b_gun_hit.png": +{ + "frame": {"x":410,"y":2,"w":66,"h":66}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":66}, + "sourceSize": {"w":66,"h":66} +}, +"tank3_body.png": +{ + "frame": {"x":58,"y":481,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3_body_destroyed.png": +{ + "frame": {"x":30,"y":481,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3_body_destroyed_shadow.png": +{ + "frame": {"x":2,"y":481,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3_body_hit.png": +{ + "frame": {"x":198,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3_body_shadow.png": +{ + "frame": {"x":170,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3_gun.png": +{ + "frame": {"x":452,"y":230,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3_gun_destroyed.png": +{ + "frame": {"x":394,"y":186,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3_gun_hit.png": +{ + "frame": {"x":336,"y":186,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3_track.png": +{ + "frame": {"x":290,"y":478,"w":22,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":22,"h":28}, + "sourceSize": {"w":22,"h":28} +}, +"tank3b_body.png": +{ + "frame": {"x":142,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3b_body_destroyed.png": +{ + "frame": {"x":114,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3b_body_hit.png": +{ + "frame": {"x":86,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3b_gun.png": +{ + "frame": {"x":234,"y":138,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3b_gun_destroyed.png": +{ + "frame": {"x":176,"y":138,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3b_gun_hit.png": +{ + "frame": {"x":118,"y":138,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3b_track.png": +{ + "frame": {"x":290,"y":448,"w":22,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":22,"h":28}, + "sourceSize": {"w":22,"h":28} +}, +"tank3c_body.png": +{ + "frame": {"x":58,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3c_body_destroyed.png": +{ + "frame": {"x":30,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3c_body_hit.png": +{ + "frame": {"x":2,"y":440,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3c_gun.png": +{ + "frame": {"x":60,"y":138,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3c_gun_destroyed.png": +{ + "frame": {"x":2,"y":138,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3c_gun_hit.png": +{ + "frame": {"x":400,"y":128,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3c_track.png": +{ + "frame": {"x":290,"y":418,"w":22,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":22,"h":28}, + "sourceSize": {"w":22,"h":28} +}, +"tank3d_body.png": +{ + "frame": {"x":370,"y":540,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3d_body_destroyed.png": +{ + "frame": {"x":342,"y":530,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3d_body_hit.png": +{ + "frame": {"x":314,"y":496,"w":26,"h":39}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":26,"h":39}, + "sourceSize": {"w":26,"h":39} +}, +"tank3d_gun.png": +{ + "frame": {"x":342,"y":128,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3d_gun_destroyed.png": +{ + "frame": {"x":400,"y":70,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3d_gun_hit.png": +{ + "frame": {"x":342,"y":70,"w":56,"h":56}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":56}, + "sourceSize": {"w":56,"h":56} +}, +"tank3d_track.png": +{ + "frame": {"x":290,"y":388,"w":22,"h":28}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":22,"h":28}, + "sourceSize": {"w":22,"h":28} +}, +"truck1_body.png": +{ + "frame": {"x":258,"y":452,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1_body_hit.png": +{ + "frame": {"x":226,"y":418,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1_body_shadow.png": +{ + "frame": {"x":194,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1_destroyed.png": +{ + "frame": {"x":162,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1_destroyed_shadow.png": +{ + "frame": {"x":130,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1b_body.png": +{ + "frame": {"x":98,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1b_body_hit.png": +{ + "frame": {"x":66,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1b_destroyed.png": +{ + "frame": {"x":34,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1c_body.png": +{ + "frame": {"x":2,"y":376,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1c_body_hit.png": +{ + "frame": {"x":474,"y":524,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck1c_destroyed.png": +{ + "frame": {"x":442,"y":524,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_body.png": +{ + "frame": {"x":410,"y":524,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_body_hit.png": +{ + "frame": {"x":378,"y":476,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_body_shadow.png": +{ + "frame": {"x":346,"y":466,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_destroyed.png": +{ + "frame": {"x":314,"y":432,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2_destroyed_shadow.png": +{ + "frame": {"x":258,"y":388,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2b_body.png": +{ + "frame": {"x":226,"y":354,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2b_body_hit.png": +{ + "frame": {"x":194,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2b_destroyed.png": +{ + "frame": {"x":162,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2c_body.png": +{ + "frame": {"x":130,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2c_body_hit.png": +{ + "frame": {"x":98,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck2c_destroyed.png": +{ + "frame": {"x":66,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_body.png": +{ + "frame": {"x":34,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_body_hit.png": +{ + "frame": {"x":2,"y":312,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_body_shadow.png": +{ + "frame": {"x":478,"y":460,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_destroyed.png": +{ + "frame": {"x":446,"y":460,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3_destroyed_shadow.png": +{ + "frame": {"x":414,"y":460,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3b_body.png": +{ + "frame": {"x":462,"y":396,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3b_body_hit.png": +{ + "frame": {"x":382,"y":412,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3b_destroyed.png": +{ + "frame": {"x":430,"y":396,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3c_body.png": +{ + "frame": {"x":350,"y":402,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3c_body_hit.png": +{ + "frame": {"x":478,"y":66,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck3c_destroyed.png": +{ + "frame": {"x":478,"y":2,"w":30,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":62}, + "sourceSize": {"w":30,"h":62} +}, +"truck_track.png": +{ + "frame": {"x":86,"y":481,"w":24,"h":23}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":24,"h":23}, + "sourceSize": {"w":24,"h":23} +}}, +"meta": { + "app": "http://www.texturepacker.com", + "version": "1.0", + "image": "ground_units.png", + "format": "RGBA8888", + "size": {"w":512,"h":1024}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:0da088f23b1454869c6ff25aabebeda2$" +} +} diff --git a/Games/Debris_Dodge/media/ground_units.png b/Games/Debris_Dodge/media/ground_units.png new file mode 100644 index 0000000000..c9c32a48a4 Binary files /dev/null and b/Games/Debris_Dodge/media/ground_units.png differ diff --git a/Games/Debris_Dodge/media/menu_music.ogg b/Games/Debris_Dodge/media/menu_music.ogg new file mode 100644 index 0000000000..d3706a6a10 Binary files /dev/null and b/Games/Debris_Dodge/media/menu_music.ogg differ diff --git a/Games/Debris_Dodge/media/metal_interaction2.wav b/Games/Debris_Dodge/media/metal_interaction2.wav new file mode 100644 index 0000000000..8519c81c36 Binary files /dev/null and b/Games/Debris_Dodge/media/metal_interaction2.wav differ diff --git a/Games/Debris_Dodge/media/names.txt b/Games/Debris_Dodge/media/names.txt new file mode 100644 index 0000000000..bae56c1746 --- /dev/null +++ b/Games/Debris_Dodge/media/names.txt @@ -0,0 +1,279 @@ +Strippy +Boffo +Buffo +Drips +Porno +Mentos +Felches +Grout +Oboe +Bumbo +Salvo +Drowny +Viagra +Acetone +Zarathustra +Styptic +Recidivo +Unctuous +Reflux +Maalox +Scurvy +Rickets +Noriega +Polyp +Garbo +Tantric +Phalanx +Bondage +Asbestos +Trenton +Aspic +Marfin +Merkin +Dropsy +Ponzi +Garrotte +Calphalon +Juvie +Schmoey Schmoe-head +Nixon +Droppo +Lesions +Boner +Clowny +Clooney +Frowny +Enfilade +Mojo +Ploop +Contusions +Animus +Pooey Poo-head +Weiner +Bac-oโ€™s +Buckminster Fuller +Domey +Subjunctive Predicate +Pestilence +Fury +Ninja +Platano +Melons +Nutout +Dangles +Tipsy +Steerage +Dunkirk +Antietam +Chins +Genuflection +Kreplach +Pringles +Shingles +Viscera +Viggo +Kielbasa +Sterno +Salieri +Flaubert +Gaspachio +Chagganooga +Nougat +Lumps +Chewie +Wookie +Kotter +Dracula +Han Solo +Jabba +Lando +Alone +Felony +Diaspora +Perspicacity +Tapenade +Detritus +Jaundice +Sbarro +Osmosis +Achtung! +Stabbo +Oleo +Tampopo +Nagano +Synergy +Effluvia +Leg Warmers +Roboto +Prozac +Eukenuba +Retsin +Rogaine +Ethel Merman +Topical Crรจme +Ointment +Cold Compress +Ace Bandage +Bourbon +Bowels +Brundlefly +Platanos +My People +Moโ€™ Broccoli +Borracho +Smuts +Nehi +Olestra +Greedo +Coolio +Consiglieri +Dinner Bell +Maligno +Angelos +Parabola +Velcro +Nubbins +Scuppers +Kippers +Flautas +Blintzes +Decoupage +Sprockets +Lupins +Gorditas +Funyuns +Manicles +Drano +Alcoa +Spores +Spleens +Placenta +Melanoma +Pathos +Explosivo +Feces +Epoxy +Ruminant +Calamari +Toffifay +Proletariat +Cop Rock +Tunisia +Cabal +Glasnost +Lanolin +Surfeit +Pillages +Acela +Wads +Bulges +Apshai +Zork +Socratic Method +Stoma +Bulldog +Bilbo +Stephen McNulty +Ball in +Schyler +Santyl +Fungible +Fergie +Verizon +Magma +Clown +Mature Content +Humpy +Flabby +Meniscus +Mellotron +M.C. Escher +Morbidly Obese +Fluffer +Strychnine +Tolstoy +String Theory +Mastication +Corpuscle +Animatronic Abraham Lincoln +Arrears +No Lo Contendere +Top Copy is Yours +Wankel +Peristalsis +Next Stop Friendship Heights +Pompatus +Tโ€™aint +Repetitive Motion Disorder +Post-traumatic Stress Disorder +Aphasia +Enlarged Prostate +Irritable Bowel Syndrome +Feline Distemper +Riboflavin +Flintstones Chewable Vitamins +Metamucils +Premature Ejaculation +Erection Lasting More Than 4 Hours +The +Quadratic Equation +Stephen Hawking +Hello Larry +Mildly Amusing +Scary to Children +Harmful If Swallowed +Do Not Take Internally +Courtesy Flush +Chuck Norris +Collect all Four +Buckaroo Bonsai Reference +Your Mom Just Died +Jonathan Coulton +Axis of Evil +Crystal Pepsi +Dr. Bob +FEMA +Broken Levee +Rhyming Couplet +Iambic Pentameter +Reforestation +Eustachian Tube +Trachea +Duodenum +Relapse +Dressing on the Side, Please, +High Fructose Corn Syrup +High Fiber Diet +Load Bearing Wall +Partially Hydrogenated +Reconstituted Meat Slurry +30,000 lbs of Bananas +Open-source Coding +Network Administrator +Subversive Meme +4th Grade Education +Conscientious Objector +Monkeydogs +Irregular Heartbeat +Asystole +Peak Oil +SEPTA IRA +Diversified Stock Portfolio +No-load Funds +0% APR for 12 Months +Zero-Sum Game +Nitrogen-fixing Crop Rotation +Frame-off Restoration +Acid Bath +Knights Templar +Mary Magdalene +Unexpected Plot Twist +Kennesaw Mountain Landis +Unintended Consequences +Odd-lot Purchases +Martyrs +Consenting Adults +Store-brand Taco Seasoning +Penultimate +Itโ€™s Not a Balloon Itโ€™s an Airship diff --git a/Games/Debris_Dodge/media/pickups.json b/Games/Debris_Dodge/media/pickups.json new file mode 100644 index 0000000000..c3cdd6acba --- /dev/null +++ b/Games/Debris_Dodge/media/pickups.json @@ -0,0 +1,68 @@ +{"frames": { + +"coin.png": +{ + "frame": {"x":2,"y":80,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"diagonal_gun.png": +{ + "frame": {"x":29,"y":54,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"life_up.png": +{ + "frame": {"x":2,"y":54,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"missile.png": +{ + "frame": {"x":29,"y":28,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"repair.png": +{ + "frame": {"x":2,"y":28,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"straight_gun.png": +{ + "frame": {"x":29,"y":2,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}, +"wingman.png": +{ + "frame": {"x":2,"y":2,"w":25,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":25,"h":24}, + "sourceSize": {"w":25,"h":24} +}}, +"meta": { + "app": "http://www.codeandweb.com/texturepacker ", + "version": "1.0", + "image": "pickups.png", + "format": "RGBA8888", + "size": {"w":64,"h":128}, + "scale": "0.5", + "smartupdate": "$TexturePacker:SmartUpdate:5bccec5fb5decb53145ba22504d88edd:1/1$" +} +} diff --git a/Games/Debris_Dodge/media/pickups.png b/Games/Debris_Dodge/media/pickups.png new file mode 100644 index 0000000000..4cdd27e732 Binary files /dev/null and b/Games/Debris_Dodge/media/pickups.png differ diff --git a/Games/Debris_Dodge/media/top_secret.ttf b/Games/Debris_Dodge/media/top_secret.ttf new file mode 100644 index 0000000000..fa8644287f Binary files /dev/null and b/Games/Debris_Dodge/media/top_secret.ttf differ diff --git a/Games/Debris_Dodge/media/trees.png b/Games/Debris_Dodge/media/trees.png new file mode 100644 index 0000000000..1d461258f2 Binary files /dev/null and b/Games/Debris_Dodge/media/trees.png differ diff --git a/Games/Debris_Dodge/media/trees_packed.json b/Games/Debris_Dodge/media/trees_packed.json new file mode 100644 index 0000000000..be7906b52e --- /dev/null +++ b/Games/Debris_Dodge/media/trees_packed.json @@ -0,0 +1,388 @@ +{"frames": { + +"tree_01.png": +{ + "frame": {"x":280,"y":183,"w":62,"h":66}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":62,"h":66}, + "sourceSize": {"w":68,"h":68} +}, +"tree_02.png": +{ + "frame": {"x":125,"y":3,"w":40,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":40,"h":38}, + "sourceSize": {"w":44,"h":42} +}, +"tree_03.png": +{ + "frame": {"x":451,"y":115,"w":66,"h":64}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":66,"h":64}, + "sourceSize": {"w":68,"h":68} +}, +"tree_04.png": +{ + "frame": {"x":383,"y":115,"w":64,"h":64}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":64,"h":64}, + "sourceSize": {"w":68,"h":68} +}, +"tree_05.png": +{ + "frame": {"x":217,"y":55,"w":54,"h":52}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":54,"h":52}, + "sourceSize": {"w":54,"h":54} +}, +"tree_06.png": +{ + "frame": {"x":3,"y":55,"w":46,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":46,"h":48}, + "sourceSize": {"w":46,"h":48} +}, +"tree_07.png": +{ + "frame": {"x":443,"y":55,"w":52,"h":56}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":52,"h":56}, + "sourceSize": {"w":56,"h":58} +}, +"tree_08.png": +{ + "frame": {"x":163,"y":55,"w":50,"h":50}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":50,"h":50}, + "sourceSize": {"w":50,"h":52} +}, +"tree_09.png": +{ + "frame": {"x":39,"y":3,"w":38,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, + "sourceSize": {"w":40,"h":40} +}, +"tree_10.png": +{ + "frame": {"x":3,"y":183,"w":64,"h":64}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":66,"h":66} +}, +"tree_11.png": +{ + "frame": {"x":365,"y":3,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":47,"h":48}, + "sourceSize": {"w":47,"h":52} +}, +"tree_12.png": +{ + "frame": {"x":416,"y":3,"w":46,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":46,"h":48}, + "sourceSize": {"w":46,"h":48} +}, +"tree_13.png": +{ + "frame": {"x":3,"y":3,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"tree_14.png": +{ + "frame": {"x":215,"y":3,"w":46,"h":44}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":46,"h":44}, + "sourceSize": {"w":46,"h":44} +}, +"tree_15.png": +{ + "frame": {"x":71,"y":183,"w":64,"h":64}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":66,"h":66} +}, +"tree_16.png": +{ + "frame": {"x":169,"y":3,"w":42,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":42,"h":42}, + "sourceSize": {"w":48,"h":46} +}, +"tree_17.png": +{ + "frame": {"x":385,"y":55,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":54,"h":54}, + "sourceSize": {"w":54,"h":58} +}, +"tree_18.png": +{ + "frame": {"x":139,"y":183,"w":68,"h":64}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":68,"h":64}, + "sourceSize": {"w":70,"h":64} +}, +"tree_19.png": +{ + "frame": {"x":67,"y":115,"w":56,"h":58}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":56,"h":58}, + "sourceSize": {"w":56,"h":60} +}, +"tree_20.png": +{ + "frame": {"x":275,"y":55,"w":48,"h":52}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":48,"h":52}, + "sourceSize": {"w":52,"h":54} +}, +"tree_21.png": +{ + "frame": {"x":3,"y":115,"w":60,"h":56}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":56}, + "sourceSize": {"w":64,"h":60} +}, +"tree_22.png": +{ + "frame": {"x":327,"y":55,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":54,"h":54}, + "sourceSize": {"w":54,"h":60} +}, +"tree_23.png": +{ + "frame": {"x":346,"y":183,"w":62,"h":66}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":62,"h":66}, + "sourceSize": {"w":64,"h":68} +}, +"tree_24.png": +{ + "frame": {"x":81,"y":3,"w":40,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":40,"h":38}, + "sourceSize": {"w":40,"h":42} +}, +"tree_25.png": +{ + "frame": {"x":255,"y":115,"w":58,"h":62}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":58,"h":62}, + "sourceSize": {"w":60,"h":62} +}, +"tree_26.png": +{ + "frame": {"x":466,"y":3,"w":48,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":50,"h":50} +}, +"tree_27.png": +{ + "frame": {"x":127,"y":115,"w":56,"h":60}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":56,"h":60}, + "sourceSize": {"w":60,"h":62} +}, +"tree_28.png": +{ + "frame": {"x":3,"y":257,"w":66,"h":70}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":66,"h":70}, + "sourceSize": {"w":70,"h":70} +}, +"tree_29.png": +{ + "frame": {"x":111,"y":55,"w":48,"h":50}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":1,"w":48,"h":50}, + "sourceSize": {"w":52,"h":52} +}, +"tree_30.png": +{ + "frame": {"x":317,"y":115,"w":62,"h":62}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":2,"w":62,"h":62}, + "sourceSize": {"w":66,"h":66} +}, +"tree_38.png": +{ + "frame": {"x":407,"y":341,"w":110,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":110,"h":114}, + "sourceSize": {"w":110,"h":120} +}, +"tree_39.png": +{ + "frame": {"x":301,"y":341,"w":102,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":102,"h":114}, + "sourceSize": {"w":106,"h":120} +}, +"tree_40.png": +{ + "frame": {"x":211,"y":183,"w":65,"h":65}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":65,"h":65}, + "sourceSize": {"w":67,"h":65} +}, +"tree_41.png": +{ + "frame": {"x":151,"y":257,"w":74,"h":72}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":74,"h":72}, + "sourceSize": {"w":82,"h":76} +}, +"tree_42.png": +{ + "frame": {"x":73,"y":257,"w":74,"h":70}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":74,"h":70}, + "sourceSize": {"w":78,"h":76} +}, +"tree_43.png": +{ + "frame": {"x":385,"y":257,"w":78,"h":78}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":78,"h":78}, + "sourceSize": {"w":84,"h":82} +}, +"tree_44.png": +{ + "frame": {"x":195,"y":341,"w":102,"h":108}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":102,"h":108}, + "sourceSize": {"w":110,"h":112} +}, +"tree_46.png": +{ + "frame": {"x":467,"y":257,"w":70,"h":80}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":8,"w":70,"h":80}, + "sourceSize": {"w":76,"h":90} +}, +"tree_47.png": +{ + "frame": {"x":53,"y":55,"w":54,"h":50}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":54,"h":50}, + "sourceSize": {"w":60,"h":56} +}, +"tree_48.png": +{ + "frame": {"x":265,"y":3,"w":46,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":3,"w":46,"h":46}, + "sourceSize": {"w":60,"h":56} +}, +"tree_49.png": +{ + "frame": {"x":315,"y":3,"w":46,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":5,"w":46,"h":46}, + "sourceSize": {"w":60,"h":56} +}, +"tree_50.png": +{ + "frame": {"x":412,"y":183,"w":68,"h":70}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":68,"h":70}, + "sourceSize": {"w":70,"h":76} +}, +"tree_51.png": +{ + "frame": {"x":229,"y":257,"w":74,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":1,"w":74,"h":74}, + "sourceSize": {"w":86,"h":78} +}, +"tree_52.png": +{ + "frame": {"x":187,"y":115,"w":64,"h":62}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":4,"w":64,"h":62}, + "sourceSize": {"w":68,"h":68} +}, +"tree_53.png": +{ + "frame": {"x":3,"y":341,"w":94,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":5,"w":94,"h":82}, + "sourceSize": {"w":94,"h":98} +}, +"tree_54.png": +{ + "frame": {"x":101,"y":341,"w":90,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":90,"h":90}, + "sourceSize": {"w":94,"h":90} +}, +"tree_55.png": +{ + "frame": {"x":307,"y":257,"w":74,"h":78}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":74,"h":78}, + "sourceSize": {"w":76,"h":82} +}}, +"meta": { + "app": "http://www.codeandweb.com/texturepacker ", + "version": "1.0", + "image": "trees_packed.png", + "format": "RGBA8888", + "size": {"w":540,"h":458}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:d8b078a9b489ef94c8641390211543b9:adf8ffbc3d0a646442fdb1855a36ac0e:a7653fb3592c74bd7bf4b33200c676f1$" +} +} diff --git a/Games/Debris_Dodge/media/trees_packed.png b/Games/Debris_Dodge/media/trees_packed.png new file mode 100644 index 0000000000..24001c4505 Binary files /dev/null and b/Games/Debris_Dodge/media/trees_packed.png differ diff --git a/Games/Debris_Dodge/media/water.png b/Games/Debris_Dodge/media/water.png new file mode 100644 index 0000000000..7c4934cb0d Binary files /dev/null and b/Games/Debris_Dodge/media/water.png differ diff --git a/Games/Debris_Dodge/spec/misc/aabb_spec.rb b/Games/Debris_Dodge/spec/misc/aabb_spec.rb new file mode 100644 index 0000000000..1ba5e3bcc3 --- /dev/null +++ b/Games/Debris_Dodge/spec/misc/aabb_spec.rb @@ -0,0 +1,85 @@ +require_relative '../../lib/misc/axis_aligned_bounding_box' +describe AxisAlignedBoundingBox do + + let(:center) { [5, 5] } + let(:half_dimension) { [10, 10] } + let(:box) { AxisAlignedBoundingBox.new( + center, half_dimension) } + + let(:point1) { [4, 7] } + let(:point2) { [0, 0] } + let(:point3) { [10, 10] } + let(:point4) { [0, 10] } + let(:point5) { [10, 0] } + + let(:point6) { [-2, 7] } + let(:point7) { [0, 11] } + let(:point8) { [11, 11] } + let(:point9) { [0, 11] } + let(:point10) { [11, 0] } + let(:point11) { [3, 15] } + let(:point12) { [11, 4] } + let(:point13) { [1, -4] } + let(:point14) { [-1, -4] } + + describe '#contains?' do + it 'detects containing point' do + expect(box.contains?(point1)).to be_truthy + expect(box.contains?(point2)).to be_truthy + expect(box.contains?(point3)).to be_truthy + expect(box.contains?(point4)).to be_truthy + expect(box.contains?(point5)).to be_truthy + end + + it 'does not detect points out of bounds' do + expect(box.contains?(point6)).to be_falsy + expect(box.contains?(point8)).to be_falsy + expect(box.contains?(point7)).to be_falsy + expect(box.contains?(point9)).to be_falsy + expect(box.contains?(point10)).to be_falsy + expect(box.contains?(point11)).to be_falsy + expect(box.contains?(point12)).to be_falsy + expect(box.contains?(point13)).to be_falsy + expect(box.contains?(point14)).to be_falsy + end + end + + describe '#intersects?' do + # center within box + let(:box1) { AxisAlignedBoundingBox.new( + [8, 8], [10, 12]) } + # center out of boundaries + let(:box2) { AxisAlignedBoundingBox.new( + [12, 12], [15, 15]) } + let(:box2_1) { AxisAlignedBoundingBox.new( + [-5, -5], [1, 1]) } + # touching corners + let(:box3) { AxisAlignedBoundingBox.new( + [-1, -1], [0, 0]) } + # out of bounds + let(:box4) { AxisAlignedBoundingBox.new( + [15, 15], [17, 17]) } + let(:box5) { AxisAlignedBoundingBox.new( + [-5, -5], [-1, -1]) } + let(:box6) { AxisAlignedBoundingBox.new( + [5, 12], [6, 13]) } + + + it 'intersects with itself' do + expect(box.intersects?(box)).to be_truthy + end + + it 'detects intersecting boxes' do + expect(box.intersects?(box1)).to be_truthy + expect(box.intersects?(box2)).to be_truthy + expect(box.intersects?(box2_1)).to be_truthy + expect(box.intersects?(box3)).to be_truthy + end + + it 'does not detect interesections out of bounds' do + expect(box.intersects?(box4)).to be_falsy + expect(box.intersects?(box5)).to be_falsy + expect(box.intersects?(box6)).to be_falsy + end + end +end diff --git a/Games/Debris_Dodge/spec/misc/quad_tree_spec.rb b/Games/Debris_Dodge/spec/misc/quad_tree_spec.rb new file mode 100644 index 0000000000..d28af31ffc --- /dev/null +++ b/Games/Debris_Dodge/spec/misc/quad_tree_spec.rb @@ -0,0 +1,137 @@ +class GameObject + attr_accessor :x, :y + def initialize(x, y) + @x, @y = x, y + end + + def location + [@x, @y] + end +end + +require_relative '../../lib/misc/axis_aligned_bounding_box' +require_relative '../../lib/misc/quad_tree' + +describe QuadTree do + let(:box) { AxisAlignedBoundingBox.new( + [5, 5], [10, 10]) } + let(:tree) { QuadTree.new(box) } + + let(:location) { [5, 5] } + let(:object) { GameObject.new(*location) } + + describe '#insert' do + subject { tree.insert(object) } + + context 'around zero coordinates' do + let(:box) { AxisAlignedBoundingBox.new( + [0, 0], [10, 10]) } + let(:location) { [0, 0] } + + it 'inserts in the middle' do + expect(subject).to be_truthy + end + end + + context 'object in center' do + it 'gets inserted' do + expect(subject).to be_truthy + end + end + + context 'object in corner' do + let(:location) { [10, 10] } + it 'gets inserted' do + expect(subject).to be_truthy + end + end + + context 'object out of bounds' do + let(:location) { [11, 11] } + it 'does not get inserted' do + expect(subject).to be_falsy + end + end + + context 'several objects' do + subject { tree.query_range(box) } + context 'to different locations' do + before do + 50.times do |i| + tree.insert( + GameObject.new( + rand(0..10), + rand(0..10))) + end + end + it 'inserts all' do + expect(subject.size).to eq 50 + end + end + + context 'to same location' do + before { 5.times { tree.insert(object.dup) } } + + it 'still inserts all' do + expect(subject.size).to eq 5 + end + end + end + end + + describe '#query_range' do + let(:query_params) { [[5, 5], [10, 10]] } + let(:query_box) { AxisAlignedBoundingBox.new(*query_params) } + subject { tree.query_range(query_box) } + + context 'empty tree' do + it 'returns empty array' do + should be_empty + end + end + + context 'single object' do + before { tree.insert(object) } + + context 'is found' do + let(:query_params) do + [object.location, object.location.map { |c| c + 1 }] + end + end + end + end + + describe '#remove' do + context 'single object' do + before do + tree.insert(object) + tree.remove(object) + end + subject { tree.query_range(box) } + + it 'removes it' do + expect(subject.size).to equal(0) + end + end + + context 'all objects' do + before do + 50.times do + tree.insert( + GameObject.new( + rand(0..10), + rand(0..10))) + end + end + subject { tree.query_range(box) } + + it 'removes it' do + expect(subject.size).to equal(50) + subject.each do |ob| + expect(tree.remove(ob)).to be_truthy + end + expect(tree.query_range(box).size).to equal(0) + end + end + end +end diff --git a/Games/Debris_Dodge/tank_island.gemspec b/Games/Debris_Dodge/tank_island.gemspec new file mode 100644 index 0000000000..086617cadd --- /dev/null +++ b/Games/Debris_Dodge/tank_island.gemspec @@ -0,0 +1,30 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) + +Gem::Specification.new do |spec| + spec.name = "tank_island" + spec.version = '1.0.5' + spec.authors = ["Tomas Varaneckas"] + spec.email = ["tomas.varaneckas@gmail.com"] + spec.summary = %q{Top down 2D shooter game that involves blowing up tanks} + spec.description = <<-EOS + This is a game built with Gosu library while writing "Developing Games With Ruby" book. + You can get the book at https://leanpub.com/developing-games-with-ruby + EOS + spec.homepage = "https://leanpub.com/developing-games-with-ruby" + spec.license = "MIT" + + spec.files = `git ls-files -z`.split("\x0") + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ["lib"] + + spec.add_development_dependency "bundler", "~> 1.6" + spec.add_development_dependency "rake", "~> 10.0" + + spec.add_runtime_dependency 'gosu', "~> 0.15.2" + spec.add_runtime_dependency 'rmagick' + spec.add_runtime_dependency 'gosu_texture_packer' + spec.add_runtime_dependency 'perlin_noise' +end diff --git a/Games/Elemental_Flux/Gameplay/Game_1.png b/Games/Elemental_Flux/Gameplay/Game_1.png new file mode 100644 index 0000000000..de80c619e1 Binary files /dev/null and b/Games/Elemental_Flux/Gameplay/Game_1.png differ diff --git a/Games/Elemental_Flux/Gameplay/Game_2.png b/Games/Elemental_Flux/Gameplay/Game_2.png new file mode 100644 index 0000000000..85a1db6a8a Binary files /dev/null and b/Games/Elemental_Flux/Gameplay/Game_2.png differ diff --git a/Games/Elemental_Flux/Gameplay/Game_3.png b/Games/Elemental_Flux/Gameplay/Game_3.png new file mode 100644 index 0000000000..2a3229876d Binary files /dev/null and b/Games/Elemental_Flux/Gameplay/Game_3.png differ diff --git a/Games/Elemental_Flux/Gameplay/desktop.ini b/Games/Elemental_Flux/Gameplay/desktop.ini new file mode 100644 index 0000000000..83495c9c05 --- /dev/null +++ b/Games/Elemental_Flux/Gameplay/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +Screenshot 2024-07-31 101153.png=@Screenshot 2024-07-31 101153,0 +Screenshot 2024-07-31 101134.png=@Screenshot 2024-07-31 101134,0 +Screenshot 2024-07-31 101122.png=@Screenshot 2024-07-31 101122,0 diff --git a/Games/Elemental_Flux/images/coal.jpeg b/Games/Elemental_Flux/images/coal.jpeg new file mode 100644 index 0000000000..bab652c611 Binary files /dev/null and b/Games/Elemental_Flux/images/coal.jpeg differ diff --git a/Games/Elemental_Flux/images/gas.jpeg b/Games/Elemental_Flux/images/gas.jpeg new file mode 100644 index 0000000000..cc26feb587 Binary files /dev/null and b/Games/Elemental_Flux/images/gas.jpeg differ diff --git a/Games/Elemental_Flux/images/geo.jpeg b/Games/Elemental_Flux/images/geo.jpeg new file mode 100644 index 0000000000..c935923ea0 Binary files /dev/null and b/Games/Elemental_Flux/images/geo.jpeg differ diff --git a/Games/Elemental_Flux/images/hydro.jpeg b/Games/Elemental_Flux/images/hydro.jpeg new file mode 100644 index 0000000000..50263bcb1b Binary files /dev/null and b/Games/Elemental_Flux/images/hydro.jpeg differ diff --git a/Games/Elemental_Flux/images/nuclear.jpeg b/Games/Elemental_Flux/images/nuclear.jpeg new file mode 100644 index 0000000000..4cffc57bb9 Binary files /dev/null and b/Games/Elemental_Flux/images/nuclear.jpeg differ diff --git a/Games/Elemental_Flux/images/oil.jpeg b/Games/Elemental_Flux/images/oil.jpeg new file mode 100644 index 0000000000..a52def9e3b Binary files /dev/null and b/Games/Elemental_Flux/images/oil.jpeg differ diff --git a/Games/Elemental_Flux/images/solor.jpeg b/Games/Elemental_Flux/images/solor.jpeg new file mode 100644 index 0000000000..ad3a208b85 Binary files /dev/null and b/Games/Elemental_Flux/images/solor.jpeg differ diff --git a/Games/Elemental_Flux/images/wind.jpeg b/Games/Elemental_Flux/images/wind.jpeg new file mode 100644 index 0000000000..b4a7ab6859 Binary files /dev/null and b/Games/Elemental_Flux/images/wind.jpeg differ diff --git a/Games/Elemental_Flux/index.html b/Games/Elemental_Flux/index.html new file mode 100644 index 0000000000..697bd3874c --- /dev/null +++ b/Games/Elemental_Flux/index.html @@ -0,0 +1,51 @@ + + + + + + Energy Sources Drag & Drop Game + + + +
+

Energy Sources: Renewable vs. Non-Renewable

+
Score: 0
+
+
+

Renewable

+
+
+

Non-Renewable

+
+
+
+ Solar +

Solar

+
+
+ Coal +

Coal

+
+
+ Wind +

Wind

+
+
+ Natural Gas +

Natural Gas

+
+
+ Hydroelectric +

Hydroelectric

+
+
+ Oil +

Oil

+
+
+
+ +
+ + + \ No newline at end of file diff --git a/Games/Elemental_Flux/readme.md b/Games/Elemental_Flux/readme.md new file mode 100644 index 0000000000..5bbfdd4958 --- /dev/null +++ b/Games/Elemental_Flux/readme.md @@ -0,0 +1,49 @@ + +# Elemental Flux: Renewable vs. Non-Renewable Showdown + +## ๐ŸŒ Description + +Elemental Flux is an engaging and educational drag-and-drop card game that challenges players to distinguish between renewable and non-renewable energy sources. In this visually stunning showdown, players must correctly categorize various energy sources, learning about sustainability and resource management in the process. + +## โœจ Features + +- Intuitive drag-and-drop gameplay +- Beautifully designed cards representing different energy sources +- Dynamic scoring system +- Educational content about renewable and non-renewable energy +- Sleek, modern user interface +- Responsive design for both desktop and mobile play + +## ๐ŸŽฎ How to Play + +1. Start the game to see a mix of energy source cards. +2. Drag each card to either the "Renewable" or "Non-Renewable" category. +3. Release the card to place it: + - Correct placement: Card stays and you earn points! + - Incorrect placement: Card returns to its original position. +4. Continue until all cards are correctly categorized. +5. Aim for a high score and quick completion time! + + +## ๐Ÿ›  Technologies Used + +- HTML5 for structure +- CSS3 for styling and animations +- JavaScript for game logic and interactivity + +## ๐ŸŽจ Customization + +Feel free to expand the game by editing `script.js`: + +- Add more energy source cards +- Adjust scoring system +- Modify game difficulty + + +## ๐Ÿš€ Installation + +1. Clone this repository . +```bash + clone git https://github.com/kunjgit/GameZone/tree/main/Games/Elemenatal_Flux +``` +2. Open the `index.html` file in a web browser to start the game. \ No newline at end of file diff --git a/Games/Elemental_Flux/script.js b/Games/Elemental_Flux/script.js new file mode 100644 index 0000000000..27905bcb9e --- /dev/null +++ b/Games/Elemental_Flux/script.js @@ -0,0 +1,109 @@ +document.addEventListener('DOMContentLoaded', () => { + const cards = document.querySelectorAll('.card'); + const dropzones = document.querySelectorAll('.dropzone'); + const cardsContainer = document.querySelector('.cards-container'); + const scoreElement = document.getElementById('score'); + const continueBtn = document.getElementById('continue-btn'); + let score = 0; + + function initGame() { + cards.forEach(card => { + card.addEventListener('dragstart', dragStart); + card.addEventListener('dragend', dragEnd); + cardsContainer.appendChild(card); + }); + + dropzones.forEach(dropzone => { + dropzone.addEventListener('dragover', dragOver); + dropzone.addEventListener('dragenter', dragEnter); + dropzone.addEventListener('dragleave', dragLeave); + dropzone.addEventListener('drop', drop); + }); + + score = 0; + updateScore(); + continueBtn.style.display = 'none'; + } + + function dragStart() { + this.classList.add('dragging'); + } + + function dragEnd() { + this.classList.remove('dragging'); + } + + function dragOver(e) { + e.preventDefault(); + } + + function dragEnter(e) { + e.preventDefault(); + this.classList.add('highlight'); + } + + function dragLeave() { + this.classList.remove('highlight'); + } + + function drop() { + this.classList.remove('highlight'); + const card = document.querySelector('.dragging'); + const cardType = card.getAttribute('data-type'); + const dropzoneType = this.id; + + if (cardType === dropzoneType) { + this.appendChild(card); + card.style.transform = 'none'; + card.style.position = 'static'; + card.style.margin = '0'; + score += 5; + updateScore(); + checkGameEnd(); + } else { + returnCardToOriginalPosition(card); + } + } + + function returnCardToOriginalPosition(card) { + const originalPosition = card.getBoundingClientRect(); + const cardClone = card.cloneNode(true); + + cardClone.style.position = 'fixed'; + cardClone.style.top = `${originalPosition.top}px`; + cardClone.style.left = `${originalPosition.left}px`; + cardClone.style.margin = '0'; + cardClone.style.zIndex = '1000'; + cardClone.style.transition = 'all 0.5s ease'; + + document.body.appendChild(cardClone); + + cardsContainer.appendChild(card); + card.style.opacity = '0'; + + setTimeout(() => { + const newPosition = card.getBoundingClientRect(); + cardClone.style.top = `${newPosition.top}px`; + cardClone.style.left = `${newPosition.left}px`; + }, 0); + + setTimeout(() => { + card.style.opacity = '1'; + document.body.removeChild(cardClone); + }, 500); + } + + function updateScore() { + scoreElement.textContent = score; + } + + function checkGameEnd() { + if (cardsContainer.children.length === 0) { + continueBtn.style.display = 'block'; + } + } + + continueBtn.addEventListener('click', initGame); + + initGame(); +}); \ No newline at end of file diff --git a/Games/Elemental_Flux/style.css b/Games/Elemental_Flux/style.css new file mode 100644 index 0000000000..c799c9f079 --- /dev/null +++ b/Games/Elemental_Flux/style.css @@ -0,0 +1,130 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: Arial, sans-serif; + background-color: #f0f0f0; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; +} + +.container { + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + padding: 1.5rem; + max-width: 600px; + width: 100%; +} + +h1 { + text-align: center; + margin-bottom: 1rem; + color: #333; + font-size: 1.5rem; +} + +.score { + text-align: center; + font-size: 1.2rem; + margin-bottom: 1rem; + color: #666; +} + +.game-area { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.5rem; +} + +.dropzone { + border: 3px dashed #ccc; + border-radius: 10px; + padding: 0.5rem; + min-height: 200px; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); + gap: 0.5rem; + align-content: start; + transition: background-color 0.3s ease; +} + +.dropzone h2 { + margin-bottom: 0.5rem; + color: #666; + grid-column: 1 / -1; + font-size: 1rem; +} + +.dropzone.highlight { + background-color: #e6f7ff; + border-color: #1890ff; +} + +.cards-container { + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); + gap: 0.5rem; + margin-top: 1rem; +} + +.card { + background-color: #fff; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + padding: 0.5rem; + text-align: center; + cursor: move; + transition: transform 0.3s ease, box-shadow 0.3s ease; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); +} + +.card img { + width: 100%; + height: 60px; + object-fit: cover; + border-radius: 4px; + margin-bottom: 0.5rem; +} + +.card p { + font-weight: bold; + color: #333; + font-size: 0.8rem; +} + +.card.dragging { + opacity: 0.5; +} + +#continue-btn { + display: block; + margin: 1rem auto 0; + padding: 0.5rem 1rem; + background-color: #1890ff; + color: #fff; + border: none; + border-radius: 4px; + font-size: 1rem; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#continue-btn:hover { + background-color: #40a9ff; +} \ No newline at end of file diff --git a/Games/Harry_Potter_Wizard_Quiz/README.md b/Games/Harry_Potter_Wizard_Quiz/README.md new file mode 100644 index 0000000000..b304fefef3 --- /dev/null +++ b/Games/Harry_Potter_Wizard_Quiz/README.md @@ -0,0 +1,38 @@ +# **Harry_Potter_Wizard_Quiz** + +--- + +
+ +## **Description ๐Ÿ“ƒ** +This game is a quiz that asks a series of 10 questions related to the Harry Potter book series. +- + +## **functionalities ๐ŸŽฎ** +This is a quiz game. +- +
+ +## **How to play? ๐Ÿ•น๏ธ** +We just have to click on the start button and the game will start playing automatically. +- + +
+ +## **Screenshots ๐Ÿ“ธ** + +
+![Screenshot 2024-08-09 145254](https://github.com/user-attachments/assets/1062e08e-10c2-4201-b8b7-f71f29f4bf5d) + +![Screenshot 2024-08-09 141828](https://github.com/user-attachments/assets/781ade96-b615-48a3-abb0-f39e8cef365f) + +![Screenshot 2024-08-09 144901](https://github.com/user-attachments/assets/be252ff9-c94e-432f-a745-212aa05f8ca8) + + +
+ +## **Working video ๐Ÿ“น** + +https://github.com/user-attachments/assets/fee060d2-bed3-46d9-b694-10564e3636db + + diff --git a/Games/Harry_Potter_Wizard_Quiz/background.mp4 b/Games/Harry_Potter_Wizard_Quiz/background.mp4 new file mode 100644 index 0000000000..03d00a1aad Binary files /dev/null and b/Games/Harry_Potter_Wizard_Quiz/background.mp4 differ diff --git a/Games/Harry_Potter_Wizard_Quiz/fonts/HarryP-MVZ6w.ttf b/Games/Harry_Potter_Wizard_Quiz/fonts/HarryP-MVZ6w.ttf new file mode 100644 index 0000000000..220e69aa93 Binary files /dev/null and b/Games/Harry_Potter_Wizard_Quiz/fonts/HarryP-MVZ6w.ttf differ diff --git a/Games/Harry_Potter_Wizard_Quiz/index.html b/Games/Harry_Potter_Wizard_Quiz/index.html new file mode 100644 index 0000000000..1cc29dcf52 --- /dev/null +++ b/Games/Harry_Potter_Wizard_Quiz/index.html @@ -0,0 +1,30 @@ + + + + + + + Harry Potter Wizard Quiz Game + + + + + +
+

Harry Potter Wizard Quiz Game

+
+

+
+
+
+

Score: 0

+

Time Left: 30 seconds

+
+
+ + + + \ No newline at end of file diff --git a/Games/Harry_Potter_Wizard_Quiz/script.js b/Games/Harry_Potter_Wizard_Quiz/script.js new file mode 100644 index 0000000000..02375e8314 --- /dev/null +++ b/Games/Harry_Potter_Wizard_Quiz/script.js @@ -0,0 +1,121 @@ +// Example data +const questions = [ + { + question: "How many people transformed into Harry Potter in the last book when Harry needed to be moved to the Weasley's house?", + answers: ["Seven", "Five", "Three", "Nine"], + correct: "Seven", + }, + { + question: "What was the prize money of the Triwizard Tournament when Harry took part in it?", + answers: [ "500 Galleons", "2000 Galleons","1000 Galleons", "750 Galleons"], + correct: "1000 Galleons", + }, + { + question: "Who gifted Harry his very first broomstick?", + answers: [ "Hagrid","Sirius Black", "Professor McGonagall", "Dumbledore"], + correct: "Sirius Black", + }, + { + question: "What animal did the imposter Mad-Eye Moody convert Malfoy into?", + answers: ["Rat", "Cat", "Toad","Ferret" ], + correct: "Ferret", + }, + { + question: "What was the first name of Professor Flitwick?", + answers: ["Filius", "Severus", "Albus", "Gilderoy"], + correct: "Filius", + }, + { + question: "What was the favourite animal of Dolores Umbridge?", + answers: ["Owl","Cat", "Rabbit", "Snake"], + correct: "Cat", + }, + { + question: "What kind of creature was Professor Firenze?", + answers: [ "Goblin", "Elf","Centaur", "Werewolf"], + correct: "Centaur", + }, + { + question: "What was James Potter's Animagus form?", + answers: ["Stag", "Dog", "Wolf", "Bear"], + correct: "Stag", + }, + { + question: "What was the color of Harry Potter's eyes?", + answers: [ "Blue", "Brown","Green", "Gray"], + correct: "Green", + }, + { + question: "What is the name of Harry Potter's pet owl?", + answers: ["Hedwig", "Scabbers", "Crookshanks", "Fawkes"], + correct: "Hedwig", + }, + + +]; + +let currentQuestionIndex = 0; +let score = 0; +let timer; +const timeLimit = 150; + +document.addEventListener("DOMContentLoaded", () => { + startGame(); +}); + +function startGame() { + score = 0; + currentQuestionIndex = 0; + document.getElementById("score").textContent = score; + startTimer(); + showQuestion(); +} + +function showQuestion() { + const question = questions[currentQuestionIndex]; + document.getElementById("question").textContent = question.question; + const answersContainer = document.getElementById("answers"); + answersContainer.innerHTML = ""; + question.answers.forEach((answer) => { + const button = document.createElement("div"); + button.textContent = answer; + button.classList.add("answer"); + button.addEventListener("click", () => checkAnswer(answer)); + answersContainer.appendChild(button); + }); +} + +function checkAnswer(selectedAnswer) { + const correctAnswer = questions[currentQuestionIndex].correct; + if (selectedAnswer === correctAnswer) { + score += 10; + document.getElementById("score").textContent = score; + // Add a sound effect or animation here + } else { + // Add a different sound effect or animation for incorrect answers + } + currentQuestionIndex++; + if (currentQuestionIndex < questions.length) { + showQuestion(); + } else { + endGame(); + } +} + +function startTimer() { + let timeLeft = timeLimit; + document.getElementById("timer").textContent = timeLeft; + timer = setInterval(() => { + timeLeft--; + document.getElementById("timer").textContent = timeLeft; + if (timeLeft <= 0) { + clearInterval(timer); + endGame(); + } + }, 1000); +} + +function endGame() { + document.getElementById("question").textContent = "Game Over!"; + document.getElementById("answers").innerHTML = ""; +} diff --git a/Games/Harry_Potter_Wizard_Quiz/start.html b/Games/Harry_Potter_Wizard_Quiz/start.html new file mode 100644 index 0000000000..1e01fc6483 --- /dev/null +++ b/Games/Harry_Potter_Wizard_Quiz/start.html @@ -0,0 +1,27 @@ + + + + + + + Harry Potter Wizard Quiz Game + + + + + +
+

Welcome to the Harry Potter Wizard Quiz Game!

+ +
+ + + + \ No newline at end of file diff --git a/Games/Harry_Potter_Wizard_Quiz/styles.css b/Games/Harry_Potter_Wizard_Quiz/styles.css new file mode 100644 index 0000000000..8d113edea9 --- /dev/null +++ b/Games/Harry_Potter_Wizard_Quiz/styles.css @@ -0,0 +1,103 @@ +@font-face { + font-family: HarryP-MVZ6w; + src: + url('fonts/HarryP-MVZ6w.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + + + +/* General Body Styles */ +body { + font-family:HarryP-MVZ6w, Arial, sans-serif; + background-color: #2e2e2e; + font-size: 18px; + color: #f0f0f0; + text-align: center; + margin: 0; + padding: 0; +} + +/* Styles for Background Video */ +#background-video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: -1; /* Place the video behind other content */ +} + +/* Styles for Startup Page */ +.startup-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100vh; + z-index: 1; /* Ensure the content is above the video */ +} + +#start-button { + padding: 15px 30px; + font-size: 1.2em; + color: #fff; + background-color: #c39a1c; /* Bright color to stand out */ + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s, transform 0.2s; +} + +#start-button:hover { + background-color: #e6b800; /* Slightly darker shade on hover */ +} + +#start-button:active { + transform: scale(0.98); /* Slightly shrink the button when clicked */ +} + +/* Styles for Quiz Page */ +.container { + max-width: 600px; + margin: auto; + padding: 20px; + background-color: #717679; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); +} + +h1 { + color:#641e1e; +} + +#question { + font-size: 1.5em; + margin-bottom: 20px; +} + +#answers { + display: flex; + flex-direction: column; + gap: 10px; +} + +.answer { + background-color: #444; + border: 1px solid #555; + border-radius: 5px; + padding: 10px; + cursor: pointer; + transition: background-color 0.3s; +} + +.answer:hover { + background-color: #555; +} + +.status { + margin-top: 20px; + font-size: 1.2em; +} diff --git a/Games/Random_Choice_Picker/README.md b/Games/Random_Choice_Picker/README.md new file mode 100644 index 0000000000..238e620bbc --- /dev/null +++ b/Games/Random_Choice_Picker/README.md @@ -0,0 +1,30 @@ +# Random Choice Picker + +**Description ๐Ÿ“ƒ** +Random Choice Picker is a simple yet fun web-based game designed to help you make decisions. Enter your choices into a textarea, and with a click of a button, the game will randomly select one of them. Perfect for picking random items or making decisions in an engaging way! + +**Functionalities ๐ŸŽฎ** +- **Input Choices:** Enter your options in a textarea, separated by commas. +- **Shuffle Button:** Press the ENTER key to shuffle the choices and randomly select one. +- **Result Display:** Shows the randomly selected choice. +- **Reset Option:** Clear inputs and results to start fresh. +- **Responsive Design:** Works well on various devices. +- **Customizable Styles:** Personalize the gameโ€™s appearance. + +**How to Play? ๐Ÿ•น๏ธ** +- **Start:** Open the game in your browser. +- **Input:** Enter your choices in the textarea, separated by commas. +- **Pick:** Press ENTER key to get a random selection. + +**Screenshots ๐Ÿ“ธ** + +![Gameplay Screenshot](https://github.com/SanskarSinghiit/GameZone/blob/main/Games/Random_Choice_Picker/assets/preview.png) + +**Getting Started ๐Ÿš€** +To get started with the Random Choice Picker, clone the repository and open the `index.html` file in your browser. + +**Installation ๐Ÿ› ๏ธ** +No installation requiredโ€”just open the HTML file in your web browser. + +--- + diff --git a/Games/Random_Choice_Picker/assets/preview.png b/Games/Random_Choice_Picker/assets/preview.png new file mode 100644 index 0000000000..0b80661814 Binary files /dev/null and b/Games/Random_Choice_Picker/assets/preview.png differ diff --git a/Games/Random_Choice_Picker/assets/random__choice_picker.webm b/Games/Random_Choice_Picker/assets/random__choice_picker.webm new file mode 100644 index 0000000000..330579aba2 Binary files /dev/null and b/Games/Random_Choice_Picker/assets/random__choice_picker.webm differ diff --git a/Games/Random_Choice_Picker/index.html b/Games/Random_Choice_Picker/index.html new file mode 100644 index 0000000000..b596a7c839 --- /dev/null +++ b/Games/Random_Choice_Picker/index.html @@ -0,0 +1,19 @@ + + + + + + + Random Choice Picker + + +
+

Enter all of the choices divided by a comma (',').
Press enter when you're done

+ + +
+
+ + + + \ No newline at end of file diff --git a/Games/Random_Choice_Picker/script.js b/Games/Random_Choice_Picker/script.js new file mode 100644 index 0000000000..be8292a1c9 --- /dev/null +++ b/Games/Random_Choice_Picker/script.js @@ -0,0 +1,69 @@ +const tagsEl = document.getElementById('tags') +const textarea = document.getElementById('textarea') + +textarea.focus() + +textarea.addEventListener('keyup', (e) => { + createTags(e.target.value) + + if(e.key === 'Enter') { + setTimeout(() => { + e.target.value = '' + }, 10) + + randomSelect() + } +}) + +function createTags(input) { + const tags = input.split(',').filter(tag => tag.trim() !== '').map(tag => tag.trim()) + + tagsEl.innerHTML = '' + + tags.forEach(tag => { + const tagEl = document.createElement('span') + tagEl.classList.add('tag') + tagEl.innerText = tag + tagsEl.appendChild(tagEl) + }) +} + +function randomSelect() { + const times = 30 + + const interval = setInterval(() => { + const randomTag = pickRandomTag() + + if (randomTag !== undefined) { + highlightTag(randomTag) + + setTimeout(() => { + unHighlightTag(randomTag) + }, 100) + } + }, 100); + + setTimeout(() => { + clearInterval(interval) + + setTimeout(() => { + const randomTag = pickRandomTag() + + highlightTag(randomTag) + }, 100) + + }, times * 100) +} + +function pickRandomTag() { + const tags = document.querySelectorAll('.tag') + return tags[Math.floor(Math.random() * tags.length)] +} + +function highlightTag(tag) { + tag.classList.add('highlight') +} + +function unHighlightTag(tag) { + tag.classList.remove('highlight') +} \ No newline at end of file diff --git a/Games/Random_Choice_Picker/style.css b/Games/Random_Choice_Picker/style.css new file mode 100644 index 0000000000..1ff8c17ff0 --- /dev/null +++ b/Games/Random_Choice_Picker/style.css @@ -0,0 +1,56 @@ +@import url('https://fonts.googleapis.com/css?family=Muli&display=swap'); + +* { + box-sizing: border-box; +} + +body { + background-color: #2b88f0; + font-family: 'Muli', sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + overflow: hidden; + margin: 0; +} + +h3 { + color: #fff; + margin: 10px 0 20px; + text-align: center; +} + +.container { + width: 500px; +} + +textarea { + border: none; + display: block; + width: 100%; + height: 100px; + font-family: inherit; + padding: 10px; + margin: 0 0 20px; + font-size: 16px; +} + +textarea:focus { + outline: none; +} + +.tag { + background-color: #f0932b; + color: #fff; + border-radius: 50px; + padding: 10px 20px; + margin: 0 5px 10px 0; + font-size: 14px; + display: inline-block; +} + +.tag.highlight { + background-color: #273c75; +} \ No newline at end of file diff --git a/Games/The_Mystery_Adventure_Game/Dream Library.jpeg b/Games/The_Mystery_Adventure_Game/Dream Library.jpeg new file mode 100644 index 0000000000..b2cf9ced9b Binary files /dev/null and b/Games/The_Mystery_Adventure_Game/Dream Library.jpeg differ diff --git a/Games/The_Mystery_Adventure_Game/README.md b/Games/The_Mystery_Adventure_Game/README.md new file mode 100644 index 0000000000..9feda83a9a --- /dev/null +++ b/Games/The_Mystery_Adventure_Game/README.md @@ -0,0 +1,52 @@ + + +# Mystery Adventure Game + +## Overview + +Embark on an engaging mystery adventure where players explore immersive environments, solve challenging puzzles, and uncover hidden secrets. Built with HTML, CSS, and JavaScript, this game offers a seamless and interactive experience for players seeking intrigue and adventure. + +## Features + +- **Immersive Environments**: Explore beautifully crafted rooms with full-screen, high-resolution backgrounds. +- **Interactive Gameplay**: Click on objects to collect items and solve puzzles, advancing the storyline. +- **Dynamic Controls**: Easily navigate between rooms and manage gameplay with start, stop, and restart options. +- **Responsive Design**: Enjoy a consistent experience across different devices and screen sizes. + +## Gameplay + +1. **Explore Rooms**: Begin your journey in the Living Room and navigate through various intriguing environments. +2. **Collect Items**: Interact with objects to gather items essential for solving puzzles. +3. **Solve Puzzles**: Use collected items to unlock new areas and discover the secrets within. +4. **Win the Game**: Successfully solve the final puzzle to achieve victory. + +## Installation + +1. Clone the repository: + ```bash + git clone https://github.com/yourusername/mystery-adventure-game.git + ``` +2. Navigate to the project directory: + ```bash + cd mystery-adventure-game + ``` +3. Open `index.html` in your preferred web browser. + +## Technologies Used + +- **HTML**: Structure and layout +- **CSS**: Styling and responsive design +- **JavaScript**: Interactive functionality and game logic + +## Contributing + +Contributions are welcome! Feel free to fork the repository, make improvements, and submit pull requests. Whether it's bug fixes, new features, or enhancements, your input is valuable. + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## Acknowledgements + +- Thanks to all contributors and users for their feedback and support. + diff --git a/Games/The_Mystery_Adventure_Game/index.html b/Games/The_Mystery_Adventure_Game/index.html new file mode 100644 index 0000000000..c36974f381 --- /dev/null +++ b/Games/The_Mystery_Adventure_Game/index.html @@ -0,0 +1,40 @@ + + + + + + Mystery Adventure Game + + + +
+

Mystery Adventure Game

+
+
+

Living Room

+
+ +
+ +
+ +
+

Inventory

+ +
+
+ + +
+
+ + + diff --git a/Games/The_Mystery_Adventure_Game/script.js b/Games/The_Mystery_Adventure_Game/script.js new file mode 100644 index 0000000000..28262325b5 --- /dev/null +++ b/Games/The_Mystery_Adventure_Game/script.js @@ -0,0 +1,89 @@ +document.addEventListener("DOMContentLoaded", () => { + const inventoryList = document.getElementById("inventoryList"); + const dialogueBox = document.getElementById("dialogue"); + const dialogueText = document.getElementById("dialogueText"); + const closeDialogueButton = document.getElementById("closeDialogue"); + const solvePuzzleButton = document.getElementById("solvePuzzleButton"); + const stopGameButton = document.getElementById("stopGameButton"); + const restartGameButton = document.getElementById("restartGameButton"); + + let gameActive = true; + + // Room Navigation + document.querySelectorAll(".navButton").forEach(button => { + button.addEventListener("click", function () { + if (gameActive) { + const targetRoomId = this.getAttribute("data-room"); + switchRoom(targetRoomId); + } + }); + }); + + // Object Interaction + document.querySelectorAll(".object").forEach(object => { + object.addEventListener("click", function () { + if (gameActive) { + const itemName = this.getAttribute("data-item"); + addToInventory(itemName); + this.style.display = "none"; + } + }); + }); + + // Solve Puzzle + solvePuzzleButton.addEventListener("click", function () { + if (gameActive) { + if (inventoryList.innerHTML.includes("Old Key") && inventoryList.innerHTML.includes("Mystery Book")) { + showDialogue("Congratulations! You solved the puzzle and uncovered the secret!"); + gameActive = false; // Game is won + } else { + showDialogue("You need more items to solve this puzzle."); + } + } + }); + + // Close Dialogue + closeDialogueButton.addEventListener("click", function () { + dialogueBox.style.display = "none"; + }); + + // Stop Game + stopGameButton.addEventListener("click", function () { + if (gameActive) { + showDialogue("The game has been stopped."); + gameActive = false; + } + }); + + // Restart Game + restartGameButton.addEventListener("click", function () { + inventoryList.innerHTML = ""; // Clear inventory + document.querySelectorAll(".object").forEach(object => { + object.style.display = "block"; // Reset objects + }); + switchRoom("room1"); // Reset to first room + gameActive = true; // Reactivate game + showDialogue("The game has been restarted."); + }); + + function addToInventory(item) { + const listItem = document.createElement("li"); + listItem.textContent = item; + inventoryList.appendChild(listItem); + } + + function switchRoom(roomId) { + document.querySelectorAll(".room").forEach(room => { + room.style.display = "none"; + }); + document.getElementById(roomId).style.display = "block"; + } + + function showDialogue(message) { + dialogueText.textContent = message; + dialogueBox.style.display = "block"; + } + + // Start game in the first room + switchRoom("room1"); +}); diff --git a/Games/The_Mystery_Adventure_Game/style.css b/Games/The_Mystery_Adventure_Game/style.css new file mode 100644 index 0000000000..948df930e4 --- /dev/null +++ b/Games/The_Mystery_Adventure_Game/style.css @@ -0,0 +1,103 @@ +body { + font-family: Arial, sans-serif; + background-color: #ffffff; + color: #fff; + text-align: center; + margin: 0; + padding: 0; + width: 100%; + height: 100vh; + background: url("https://c4.wallpaperflare.com/wallpaper/556/382/458/fantasy-art-artwork-fan-art-science-fiction-wallpaper-preview.jpg"); + + +} +@keyframes gradientAnimation { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} + +#game { + max-width: 800px; + margin: 20px auto; + padding: 20px; + background-color: #444; + border-radius: 8px; + background: url("https://c4.wallpaperflare.com/wallpaper/780/165/226/digital-art-artwork-video-games-bloodborne-wallpaper-preview.jpg"); +} +.room { + position: relative; + width: 100%; + height: 400px; + background-size: cover; + margin-bottom: 20px; + display: none; +} + +.room h2 { + margin-top: 0; +} + +#room1 { + background-image: url('https://media.istockphoto.com/id/1283022900/photo/open-door-with-key.jpg?s=612x612&w=0&k=20&c=TazUzQSI-vN13ccK1qgTjuXgIy-vRDx-hZPPGnP7nkw='); +} + +#room2 { + background-image: url('https://c0.wallpaperflare.com/preview/420/125/157/book-float-library-bookstore.jpg'); +} + +.object { + position: absolute; + width: 30px; + height: 30px; + background-color: rgba(255, 255, 0, 0.7); + border-radius: 50%; + cursor: pointer; +} + +#inventory { + text-align: left; +} + +#inventoryList { + list-style-type: none; + padding: 0; +} + +.navButton { + padding: 10px; + margin: 10px; + background-color: #555; + border: none; + color: white; + cursor: pointer; + border-radius: 5px; +} + +#dialogue { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: #555; + padding: 20px; + border-radius: 10px; +} + +#dialogueText { + margin-bottom: 20px; +} + +#controls { + margin-top: 20px; +} + +#controls button { + padding: 10px; + margin: 5px; + background-color: #555; + border: none; + color: white; + cursor: pointer; + border-radius: 5px; +} diff --git a/README.md b/README.md index 02c2fc9380..7e74f29c7c 100644 --- a/README.md +++ b/README.md @@ -357,10 +357,17 @@ This repository also provides one such platforms where contributers come over an | [Modulo_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Modulo_Game) | | [Airhockey_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Airhockey_Game) | +| [Elemental Flux Game](https://github.com/kunjgit/GameZone/tree/main/Games/Elemental_Flux)| + | [Am_I_the_number](https://github.com/kunjgit/GameZone/tree/main/Games/Am_I_the_number) | |[Gem_Cruncher](https://github.com/kunjgit/GameZone/tree/main/Games/Gem_Cruncher)| +| [Ball and Paddle game](https://github.com/kunjgit/GameZone/tree/main/Games/Ball-And-Paddle-Game) | + +|[Harry Potter Wizards Quiz](https://github.com/kunjgit/GameZone/tree/main/Games/Harry_Potter_Wizards_Quiz)| + +
@@ -452,6 +459,7 @@ Terms and conditions for use, reproduction and distribution are under the [Apach | [Gravity_Drops](https://github.com/kunjgit/GameZone/tree/main/Games/Gravity_Drops) | | [Sky_Lift_Dash](https://github.com/kunjgit/GameZone/tree/main/Games/Sky_Lift_Dash) | | [Block_Vault](https://github.com/kunjgit/GameZone/tree/main/Games/Block_Vault) | +| [Random_Choice_Picker](https://github.com/kunjgit/GameZone/tree/main/Games/Random_Choice_Picker) |
@@ -916,8 +924,12 @@ This repository also provides one such platforms where contributers come over an |[Idle_miner](https://github.com/kunjgit/GameZone/tree/main/Games/Idle_miner)| [Five_Nights_at_Freddys](https://github.com/kunjgit/GameZone/tree/main/Games/Five_Nights_at_Freddys) | [Penalty_Shootout_Game] (https://github.com/kunjgit/GameZone/tree/main/Games/Penalty_Shootout_Game)| |[Snake_Gun_Water](https://github.com/kunjgit/GameZone/tree/main/Games/Snake_Gun_Water)| | [Drum_kit] (https://github.com/kunjgit/GameZone/tree/main/Games/Drum_kit)| +| [Prime-No-Finder-Game] (https://github.com/kunjgit/GameZone/tree/main/Games/Prime-No-Finder-Game)| +| [Debris_Dodge](https://github.com/kunjgit/GameZone/tree/main/Games/Debris_Dodge)| + | [Prime-No-Finder-Game] (https://github.com/kunjgit/GameZone/tree/main/Games/Prime-No-Finder-Game)| | [Synonym-Typing-Game] (https://github.com/kunjgit/GameZone/tree/main/Games/Synonym-Typing-Game)| +| [Color-Blink-Challenge] (https://github.com/kunjgit/GameZone/tree/main/Games/Color-Blink-Challenge)|

Back to top

@@ -1715,6 +1727,7 @@ This repository also provides one such platforms where contributers come over an |[Tower_Building_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Tower_Building_Game)| |[Cross_Road_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Cross_Road_Game)| +|[The_Mystery_Adventure_game](https://github.com/kunjgit/GameZone/tree/main/Games/The_Mystery_Adventure_Game)| diff --git a/assets/images/Ball-And-Paddle-game.md b/assets/images/Ball-And-Paddle-game.md new file mode 100644 index 0000000000..369a4ea78c --- /dev/null +++ b/assets/images/Ball-And-Paddle-game.md @@ -0,0 +1,3 @@ +![image](https://github.com/user-attachments/assets/4177d469-857b-4714-8004-1ac03203fac3) + +![image](https://github.com/user-attachments/assets/6d04c538-7592-4f38-912d-e46d0a8d487f) diff --git a/assets/images/Color Blink Challenge.png b/assets/images/Color Blink Challenge.png new file mode 100644 index 0000000000..47732ddc0d Binary files /dev/null and b/assets/images/Color Blink Challenge.png differ diff --git a/assets/images/Harry_Potter_Wizard_Quiz.png b/assets/images/Harry_Potter_Wizard_Quiz.png new file mode 100644 index 0000000000..1d5ace069f Binary files /dev/null and b/assets/images/Harry_Potter_Wizard_Quiz.png differ diff --git a/assets/images/Random_Choice_Picker.png b/assets/images/Random_Choice_Picker.png new file mode 100644 index 0000000000..0b80661814 Binary files /dev/null and b/assets/images/Random_Choice_Picker.png differ diff --git a/assets/images/The Mystery Adventure Game.png b/assets/images/The Mystery Adventure Game.png new file mode 100644 index 0000000000..8f129d842f Binary files /dev/null and b/assets/images/The Mystery Adventure Game.png differ diff --git a/assets/images/debris dodge.png b/assets/images/debris dodge.png new file mode 100644 index 0000000000..4084447392 Binary files /dev/null and b/assets/images/debris dodge.png differ diff --git a/assets/js/gamesData.json b/assets/js/gamesData.json index c573ee4943..cbcb6f7714 100644 --- a/assets/js/gamesData.json +++ b/assets/js/gamesData.json @@ -3229,16 +3229,32 @@ "gameUrl": "Block_Vault", "thumbnailUrl": "Block_Vault.png" }, + + + + "646":{ + "gameTitle" : "Harry Potter Wizard Quiz", + "gameUrl": "Harry_Potter_Wizard_Quiz/start.html", + "thumbnailUrl": "Harry_Potter_Wizard_Quiz.png" + } + + + "647":{ "gameTitle" : "Droop Dash Game", "gameUrl": "Drop_Dash_Game", "thumbnailUrl": "Drop_Dash_Game.png" - }, - "647":{ + }, + "648":{ "gameTitle" : "Gravity Switch Game", "gameUrl": "Gravity_Switch_Game", "thumbnailUrl": "Gravity_Switch_Game.png" + "649":{ + "gameTitle" : "Random Choice Picker", + "gameUrl": "Random_Choice_Picker", + "thumbnailUrl": "Drop_Dash_Game.png" + } } diff --git a/assets/js/index.js b/assets/js/index.js index 0e6a7f2ba0..c82a53d22b 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -3,7 +3,7 @@ const generateLiTags = (gamesData, searchText = "") => { const liTags = []; searchText = searchText.trim().toLowerCase(); // Trim whitespace and convert to lowercase - let lengthOfJson = Object.keys(gamesData).length; // get the no. of games of Json to list them all + let lengthOfJson = Object.keys(gamesData).length+10; // get the no. of games of Json to list them all for (let tagNumber = 1; tagNumber <= lengthOfJson; tagNumber++) { const gameData = gamesData[tagNumber.toString()];