// 2012-12-17 16:40:53
// Start to implement the Asteroids flash edition
// just translate the python code into AS3.0, I
// will optimize it later
// First I am going to learn how to load image and
// sound into this mini-project.
// 2012-12-19 20:49:02 Using global variables is not a good idea.
// 2012-12-20 15:38:26 I can't stop thinking about implementing this little game.
// What about my CET6!!?? It's really the end of the world!!!
// Once I started, I just can't stop doing this.
// 2012-12-25 12:54:25 finally I think that I have figured out how to deal with the keyboard event.
// using an array which stores all the keyboard event.
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.ui.Keyboard;
import flash.utils.Timer;
// import flash.media.Sound;
/**
*
* @author Sean
*/
[SWF(width="800", height="600", frameRate="60")]
public class Asteroids extends Sprite
{
public static var image_assets:Array;
protected var score:int = 0;
protected var lives:int = 3;
protected var time:int = 0;
public static const WIDTH:int = 800;
public static const HEIGHT:int = 600;
protected var my_ship:Ship;
protected var rock_group:Array;
protected var missile_group:Array;
protected var explosion_group:Array;
protected var loader:Loader;
protected var canvas:BitmapData;
protected var image_url:Array;
protected var counter:int = 0;
protected var frame:int = 0;
protected const SIZE:Rectangle = new Rectangle(0, 0, 128, 128);
protected var keydown:Object;
protected var timer:Timer;
protected static const TIMER_DELAY:Number = 1 * 1000;
public function Asteroids()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
loadingGame();
}
protected function loadingGame():void {
canvas = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xFF000000);
image_assets = new Array();
loader = new Loader();
image_url = new Array("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_brown.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png",
"http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_orange.png");
loadImage();
}
protected function loadImage():void {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
loader.load(new URLRequest(image_url[counter++]));
}
// protected function loadSound():void {
//
// }
protected function loaded(event:Event):void {
image_assets.push(Bitmap(LoaderInfo(event.target).content).bitmapData);
trace(image_assets.length);
if (counter == image_url.length)
{
trace("successfully loaded all images!");
initGame();
}
else
loadImage();
}
public function initGame():void {
keydown = new Array();
var bmp:Bitmap = new Bitmap(canvas);
addChild(bmp);
my_ship = new Ship(Vector.<Number>([WIDTH / 2, HEIGHT / 2]), Vector.<Number>([0, 0]), 0, 0, image_assets[3]);
addChild(my_ship);
// my_ship.focusRect = false;
stage.focus = stage;
rock_group = new Array();
missile_group = new Array();
explosion_group = new Array();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeydown, false);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyup, false);
timer = new Timer(TIMER_DELAY);
timer.addEventListener(TimerEvent.TIMER, rock_spawner);
timer.start();
this.addEventListener(MouseEvent.CLICK, onClick);
this.addEventListener(Event.ENTER_FRAME, draw);
}
protected function onClick(evt:MouseEvent):void {
stage.focus = my_ship;
}
protected function draw(evt:Event = null):void {
// animated background, need to be implemented...
canvas.draw(image_assets[0]);
var transform:Matrix = new Matrix();
transform.translate(10, 0);
transform.scale(WIDTH / image_assets[1].width, HEIGHT / image_assets[1].height);
canvas.draw(image_assets[1], transform, null, null, null, true);
// draw ship and sprites
my_ship.draw();
// process group of rocks and missiles
process_sprite_group(rock_group);
process_sprite_group(missile_group);
process_sprite_group(explosion_group);
// update ship and sprites
my_ship.update();
// detect collisions
if (group_collide(rock_group, my_ship))
lives -= 1;
// trace(lives);
score += (group_group_collide(missile_group, rock_group)) * 10;
}
protected function process_sprite_group(sprite_group:Array):void {
// this function is going to draw each of the sprite on the canvas
var alive:Boolean = true;
if (sprite_group.length) {
for each (var sprite:my_sprite in Vector.<my_sprite>(sprite_group)) {
stage.addChild(sprite);
sprite.draw();
alive = sprite.update();
if (!alive) {
stage.removeChild(sprite);
sprite_group.shift();
}
}
}
}
protected function group_collide(sprite_group:Array, other_object:Sprite):int {
var counter:int = 0;
for each (var sprite:my_sprite in Vector.<my_sprite>(sprite_group)) {
if (sprite.collide(other_object)) {
explosion_group.push(new my_sprite(sprite.get_position(), Vector.<Number>([0, 0]), 0, 0, image_assets[6], 24, 0, true));
stage.removeChild(sprite);
sprite_group.splice(sprite_group.indexOf(sprite), 1);
counter += 1
}
}
return counter;
}
protected function group_group_collide(sprite_group1:Array, sprite_group2:Array):int {
var counter:int = 0;
for each (var sprite:my_sprite in Vector.<my_sprite>(sprite_group1)) {
// check if the missile collides with the any of the rocks
if (group_collide(sprite_group2, sprite)) {
stage.removeChild(sprite);
sprite_group1.splice(sprite_group1.indexOf(sprite), 1);
counter += 1;
}
}
return counter;
}
protected function rock_spawner(evt:TimerEvent = null):void {
if (rock_group.length < 12) {
// I still need to make sure that rock won't spawn in the place where the ship are
var rock_pos:Vector.<Number> = new Vector.<Number>();
rock_pos = Vector.<Number>([Math.random() * WIDTH, Math.random() * HEIGHT]);
var rock_vel:Vector.<Number> = new Vector.<Number>();
rock_vel = Vector.<Number>([Math.random() * 1.6 - .8, Math.random() * 1.6 - .8]);
var rock_avel:Number = Math.random() * 4 - 2;
var a_rock:my_sprite = new my_sprite(rock_pos, rock_vel, 0, rock_avel, image_assets[5]);
rock_group.push(a_rock);
}
}
// help function
protected function is_in_keydown(key:uint):Boolean {
for (var key_code in keydown) {
if (key == key_code)
return true;
}
return false;
}
protected function onKeydown(evt:KeyboardEvent):void {
if (evt.keyCode != Keyboard.LEFT && evt.keyCode != Keyboard.RIGHT && evt.keyCode != Keyboard.UP && evt.keyCode != Keyboard.SPACE)
return;
if (!is_in_keydown(evt.keyCode))
keydown[evt.keyCode] = true;
if (keydown[evt.keyCode]) {
switch (evt.keyCode) {
case Keyboard.LEFT:
my_ship.decrement_angle_vel();
break;
case Keyboard.RIGHT:
my_ship.increment_angle_vel();
break;
case Keyboard.UP:
my_ship.set_thrust(true);
break;
case Keyboard.SPACE:
my_ship.shoot(missile_group);
}
keydown[evt.keyCode] = false;
}
}
protected function onKeyup(evt:KeyboardEvent):void {
if (is_in_keydown(evt.keyCode))
delete keydown[evt.keyCode];
switch (evt.keyCode) {
case Keyboard.LEFT:
my_ship.increment_angle_vel();
break;
case Keyboard.RIGHT:
my_ship.decrement_angle_vel();
break;
case Keyboard.UP:
my_ship.set_thrust(false);
break;
}
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.media.SoundChannel;
import flash.net.URLRequest;
class Ship extends Sprite {
protected static const COF:Number = 0.03;
protected static const ACCELERATION:Number = .6;
protected var scale:int = 1;
protected var vel:Vector.<Number>;
protected var thrust:Boolean;
protected var angle_vel:Number;
protected var image:BitmapData;
protected var image_data:BitmapData;
protected var SIZE:Rectangle;
protected var my_ship_image:Bitmap;
protected var sound_channel:SoundChannel;
public function Ship(pos:Vector.<Number>, vel:Vector.<Number>, angle:Number, angle_vel:Number, image:BitmapData) {
SIZE = new Rectangle(0, 0, image.height, image.height);
this.x = pos[0];
this.y = pos[1];
this.vel = new Vector.<Number>();
this.vel = vel;
this.rotation = angle;
this.angle_vel = angle_vel;
this.image_data = image;
this.image = new BitmapData(SIZE.width, SIZE.height);
my_ship_image = new Bitmap(this.image);
my_ship_image.x = -SIZE.width / 2;
my_ship_image.y = -SIZE.height / 2;
addChild(my_ship_image);
}
public function increment_angle_vel():void {
this.angle_vel += 3;
}
public function decrement_angle_vel():void {
this.angle_vel -= 3;
}
public function shoot(missile_group:Array):void {
var forward:Vector.<Number> = Vector.<Number>(angle_to_vector(this.rotation * Math.PI / 180));
var vel:Number = 5;
var missile_pos:Vector.<Number> = new Vector.<Number>();
missile_pos = Vector.<Number>([this.x + (SIZE.width / 2) * forward[0], this.y + (SIZE.width / 2) * forward[1]]);
var missile_vel:Vector.<Number> = new Vector.<Number>();
missile_vel = Vector.<Number>([this.vel[0] + vel * forward[0], this.vel[1] + vel * forward[1]]);
var a_missile:my_sprite = new my_sprite(missile_pos, missile_vel, 0, 0, Asteroids.image_assets[4], 50);
missile_group.push(a_missile);
}
public function set_thrust(on:Boolean):void {
this.thrust = on;
if (on) {
sound_channel = sound.ship_thrust_sound.play(0);
}
else
sound_channel.stop();
}
public function get_position():Vector.<Number> {
return Vector.<Number>([this.x, this.y]);
}
public function draw():void {
image.fillRect(SIZE, 0);
var transform:Matrix = new Matrix();
transform.createBox(scale, scale, 0, -int(this.thrust) * SIZE.width, 0);
//use SIZE to clip the shifted graphic to the correct position and size
image.draw(image_data, transform, null, null, SIZE);
}
public function update():void {
// position update
this.x = this.x < 0 ? Asteroids.WIDTH : this.x;
this.y = this.y < 0 ? Asteroids.HEIGHT : this.y;
this.x = (this.x + this.vel[0]) % Asteroids.WIDTH;
this.y = (this.y + this.vel[1]) % Asteroids.HEIGHT;
// friction update
this.vel[0] *= (1 - COF);
this.vel[1] *= (1 - COF);
// accelerate
if (this.thrust) {
var forward:Vector.<Number> = Vector.<Number>(angle_to_vector(this.rotation * Math.PI / 180));
this.vel[0] += forward[0] * ACCELERATION;
this.vel[1] += forward[1] * ACCELERATION;
}
// angle update
this.rotation += this.angle_vel;
}
protected function angle_to_vector(ang:Number):Vector.<Number> {
return Vector.<Number>([Math.cos(ang), Math.sin(ang)]);
}
}
class my_sprite extends Sprite {
protected var vel:Vector.<Number>;
protected var angle_vel:Number;
protected var image:BitmapData;
protected var image_data:BitmapData;
protected var my_sprite_image:Bitmap;
protected var SIZE:Rectangle;
protected var animated:Boolean;
protected var radius:int;
protected var lifespan:Number;
protected var age:int;
public function my_sprite(pos:Vector.<Number>, vel:Vector.<Number>, angle:Number, angle_vel:Number, image:BitmapData,
lifespan:Number = Number.MAX_VALUE, age:int = 0, animated:Boolean = false) {
SIZE = new Rectangle(0, 0, image.height, image.height);
this.x = pos[0];
this.y = pos[1];
this.vel = new Vector.<Number>();
this.vel.push(vel[0]);
this.vel.push(vel[1]);
this.rotation = angle;
this.angle_vel = angle_vel;
this.image_data = image;
this.image = new BitmapData(image.height, image.height);
this.my_sprite_image = new Bitmap(this.image);
my_sprite_image.x = -SIZE.width / 2;
my_sprite_image.y = -SIZE.height / 2;
this.lifespan = lifespan;
this.animated = animated;
addChild(my_sprite_image);
}
public function get_position():Vector.<Number> {
return Vector.<Number>([this.x, this.y]);
}
public function collide(other_object:DisplayObject):Boolean {
return this.hitTestObject(other_object);
}
public function draw():void {
if (!this.animated) {
image.fillRect(image.rect, 0);
image.draw(image_data);
}
else {
image.fillRect(SIZE, 0);
var transform:Matrix = new Matrix();
transform.createBox(1, 1, 0, -age * SIZE.width, 0);
//use SIZE to clip the shifted graphic to the correct position and size
image.draw(image_data, transform, null, null, SIZE);
}
}
public function update():Boolean {
// position update
this.x = this.x < 0 ? Asteroids.WIDTH : this.x;
this.y = this.y < 0 ? Asteroids.HEIGHT : this.y;
this.x = (this.x + this.vel[0]) % Asteroids.WIDTH;
this.y = (this.y + this.vel[1]) % Asteroids.HEIGHT;
// angle update
this.rotation += this.angle_vel;
// aging
this.age += 1
// if true, he/she is still alive, or otherwise
if (this.age <= this.lifespan)
return true;
else
return false;
}
}
import flash.media.Sound;
class sound {
public static var soundtrack:Sound = new Sound(new URLRequest("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3"));
public static var missile_sound:Sound = new Sound(new URLRequest("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3"));
public static var ship_thrust_sound:Sound = new Sound(new URLRequest("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3"));
public static var explosion_sound:Sound = new Sound(new URLRequest("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3"));
}
//
//import flash.events.Event;
//import flash.display.Loader;
//import flash.display.LoaderInfo;
//class image {
// public static var debris_image:BitmapData;
// public static var nebula_image:BitmapData;
// public static var splash_image:BitmapData;
// public static var ship_image:BitmapData;
// public static var missile_image:BitmapData;
// public static var asteroid_image:BitmapData;
// public static var explosion_image:BitmapData;
//
// protected var counter:int = 0;
// protected var image_loader:Loader;
// protected var image_url:Array;
//
// public function image() {
// image_loader = new Loader();
// image_url = new Array("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_brown.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png",
// "http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png");
// image_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
// loadImage();
// }
//
// protected function loadImage():void {
// image_loader.load(new URLRequest(image_url[counter++]));
// }
//
// protected function loaded(evt:Event):void {
// var temp_data:BitmapData = Bitmap(LoaderInfo(evt.target).content).bitmapData;
// if (counter < 8)
// switch (counter - 1) {
// case 0:
// debris_image = temp_data;
// case 1:
// nebula_image = temp_data;
// case 2:
// splash_image = temp_data;
// case 3:
// ship_image = temp_data;
// case 4:
// missile_image = temp_data;
// case 5:
// asteroid_image = temp_data;
// case 6:
// explosion_image = temp_data;
// }
// else
// loadImage();
// }
//}
转载于:https://my.oschina.net/seandor/blog/97420