Понедельник, 25 Ноября 2024, 00:17

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Flex и ActionScript 3.0 для создания мини-флеш игр. Часть 2
B1zDelKinДата: Суббота, 23 Января 2010, 15:32 | Сообщение # 1
частый гость
Сейчас нет на сайте
В данном уроке мы создадим простую игру, являющуюся внебрачным сыном арканоида и пинг-понга.
Суть игры в том, чтобы отбить мячик до того как он коснется вашей стороны экрана. На другой стороне нам оппонирует компьютерный игрок, занимающийся аналогичным делом.

Для этого нам понадобится создать 2 новых класса соответсвенно для нашего шарика и для платформы, представялющей игроков. Взаимодействие объектов будет определяться путем обнаружения столкновений между ними, меняя тем самым их поведение.

Создаем новый класс, назовем его как-нибудь по оригинальнее, например Ball. Не забудем расширить его от класса Sprite.
Данный класс во много напоминает собственный курсор из предыдущего урока, за одним исключением - для мячика мы применим радиальную градиентную заливку.

Ball.as :

Code

package    
{
import flash.display.*;
import flash.geom.Matrix;
     
public class Ball extends Sprite
{
      
   public function Ball()   
   {
    var matr:Matrix = new Matrix(); /// для задания одного из параметров заливки нам понадобиться матрица, тут мы ее создаем
    matr.createGradientBox(15, 15, 0, -5, -5); /// тут мы определям ее размеры, вращение и координаты
       
    this.graphics.lineStyle(1);
                     /// тип градиента, массивы для цвета, прозрачности, расположения цветов, задание матрицы   
    this.graphics.beginGradientFill(GradientType.RADIAL, [0xFF0000, 0xFFC000], [1, 1], [50, 255], matr, SpreadMethod.REFLECT);
    this.graphics.drawCircle(0, 0, 15);
    this.graphics.endFill();
   }
      
}

}

Теперь создадим новый класс для "рокетки", назовем его Paddle.
По скольку данный класс будет нами использован для задания как игрока таки его противника, у нас резонно возникает желание задать различный внешний вид рокеток. Сделать это можно используя параметы функции-конструкторв класса Paddle. Изменять таким образом можно все что душе угодно, но здесь мы ограничемся заданием цвета.

Итак в параметрах функции public function Paddle() в круглых скобках пишем colors:Array. Мы используем массив в качестве типа параметра потому, что цвет градиентной заливки определяется массивом, элементами которого являются цвета. В нашем случаем мы используем 2 цвета для задания градиента, но прошу обратить внимание на то, что ряд других параметров функции beginGradientFill также представляет собой массивы. Количество элементов данных массивов одинаково и равно числу заданных цветов.

Эти параметры связаны друг с другом и порядковый номер эелемента соответсвующего массива относится к цвету с точно таким же порядковым номером. Всего можно задать 15 цветов (то есть максимально массив может содержать 15 элементов).

Paddle.as :

Code

package    
{
import flash.display.*;
import flash.geom.Matrix;
     
public class Paddle extends Sprite
{
      
   public function Paddle(colors:Array)   
   {
    var matr:Matrix = new Matrix();
    matr.createGradientBox(100, 20, 45, 0, 0);
       
    this.graphics.lineStyle(1);
    this.graphics.beginGradientFill(GradientType.LINEAR, colors, [1, 1], [0, 255], matr); /// для рокетки мы использовали линейный тип заливки, параметр colors задает цвета принятые функцией-конструтором во время создания экземпляра класса Paddle
    this.graphics.drawRect(0, 0, 100, 20);
    this.graphics.endFill();
   }
      
}

}

Теперь открываем Main.mxml и пишем саму игру.

Создаем глобальные переменные для нашей игры:

Code

private var ball:Ball;                 /// создаем мяч
private var player:Paddle;         /// создаем игрока
private var enemy:Paddle;       /// создаем компьютерного игрока
private var xDir:int = 10;          /// переменные задающие направление движения мячика по осям x и y
private var yDir:int = -10;
private var targetX:Number = 0;  /// числовая переменная, обозначающая место куда мы ходим привести нашу рокетку (определяется движением мыши)
private var easing:Number = 3;  /// сглаживание движения   

Главная функция задающая игру после запуска приложения:

Code

private function init():void
{
   Mouse.hide(); /// прячем курсор
       
   player = new Paddle([0x00FF00, 0x0000FF]);  /// создаем экземпляр класса Paddle для игрока и задаем ему цвета.
   player.x = 200;
   player.y = 350;
   stage.addChild(player);
       
   enemy = new Paddle([0xFF0000, 0xFF00FF]);  /// таже операция и для врага
   enemy.x = 200;
   enemy.y = 30;
   stage.addChild(enemy);
       
   player.addEventListener(Event.ENTER_FRAME, movePlayer); /// задаем функцию игрока вызываемую при каждом обновлении кадра
   enemy.addEventListener(Event.ENTER_FRAME, moveEnemy);  /// то есть в дангой игре мы используем покадровую анимацию
       
   ball = new Ball();  /// создаем мячик
   ball.x = 250;
   ball.y = 200;
   stage.addChild(ball);
       
   ball.addEventListener(Event.ENTER_FRAME, moveBall); /// двигаем мяч
}

Далее сами функции движения объектов с подробными комментариями:

Code

private function moveBall(e:Event):void
{
   /// если мяч уперся в какую либо из стен игрового экрана - меняем его направление на противоположное (отражаем)
                   
                  if (ball.x <= 0) {   
    xDir *= -1;
   }
   else if (ball.x >= this.width - ball.width/2) {
    xDir *= -1;
   }

                  //// здесь иы используем функцию hitTestObject() объекта ball для проверки столкновения с объектами player и enemy.
                  //// в случае обнаружения оного, функция возвращает значение [b]true[/b] и мы также как и в случае со стенкой отражаем мяч

   if (ball.hitTestObject(player)) {              
    yDir *= -1;
   }
   else if (ball.hitTestObject(enemy)) {
    yDir *= -1;
   }

   if (ball.y <= 0) {
    yDir *= -1;
   }
   else if (ball.y >= this.height - ball.height/2) {
    yDir *= -1;
   }
       
   ball.x += xDir; //// двигаем мяч согласно определнному выше направлению по обоим осям
   ball.y += yDir;
}

private function movePlayer(e:Event):void
{
   if (this.mouseX < player.width/2) {             //// если мышь левее точки равной половине рокетки, то не даем рокетке выйти за пределы экрана
    targetX = 0;
   }
   else if(this.mouseX > this.width - player.width/2) {   //// тоже самое для правой границы
    targetX = this.width - player.width;
   }
   else {                    //// если куроср между этими двумя точками, то координаты цели движения равны положению мыши минус половина ширины рокетки
    targetX = this.mouseX - player.width/2;
   }
        
   player.x += (targetX/2 - player.x/2) / easing;      //// координаты местоположения игрока опредеяются следующей формулой, где easing это параметр задающий плавность движения рокетки, своего рода энерции
}
      
private function moveEnemy(e:Event):void
{   
   //// функция движения компьютера очень похожа по механизму на функцию игрока, думаю тут все понятно
                  //// иллюзия искусственного интеллекта здесь создается за счет постоянного следования рокетки за самим мячом, а не за курсором мыши как в случае с игроком
                 //// однако выиграть у того ИИ вряд ли получится) у меня не вышло... хотя с увеличением энерции (easing) это становится все легче

                  var enemyTargetX:Number;
   enemyTargetX = ball.x - enemy.width / 2;

   if (enemyTargetX <= 0) {
    enemyTargetX = 0;
   }
   else if (enemyTargetX >= this.width - enemy.width / 2) {
    enemyTargetX = this.width - enemy.width / 2;
   }
       
   enemy.x += (enemyTargetX / 2 - enemy.x / 2) / easing;
}

Полный код Main.mxml

Code

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="500" height="400" applicationComplete="init()" frameRate="24">
   <mx:Script>
    <![CDATA[
import flash.events.Event;
import flash.events.MouseEvent;
private var ball:Ball;
private var player:Paddle;
private var enemy:Paddle;
private var xDir:int = 10;
private var yDir:int = -10;
private var targetX:Number = 0;
private var easing:Number = 3;
      
private function init():void
{
   Mouse.hide();
       
   player = new Paddle([0x00FF00, 0x0000FF]);
   player.x = 200;
   player.y = 350;
   stage.addChild(player);
       
   enemy = new Paddle([0xFF0000, 0xFF00FF]);
   enemy.x = 200;
   enemy.y = 30;
   stage.addChild(enemy);
       
   player.addEventListener(Event.ENTER_FRAME, movePlayer);
   enemy.addEventListener(Event.ENTER_FRAME, moveEnemy);
       
   ball = new Ball();
   ball.x = 250;
   ball.y = 200;
   stage.addChild(ball);
       
   ball.addEventListener(Event.ENTER_FRAME, moveBall);
}
      
private function moveBall(e:Event):void
{
   if (ball.x <= 0) {
    xDir *= -1;
   }
   else if (ball.x >= this.width - ball.width/2) {
    xDir *= -1;
   }
   if (ball.hitTestObject(player)) {
    yDir *= -1;
   }
   else if (ball.hitTestObject(enemy)) {
    yDir *= -1;
   }
   if (ball.y <= 0) {
    yDir *= -1;
   }
   else if (ball.y >= this.height - ball.height/2) {
    yDir *= -1;
   }
       
   ball.x += xDir;
   ball.y += yDir;
}
private function movePlayer(e:Event):void
{
   if (this.mouseX < player.width/2) {
    targetX = 0;
   }
   else if(this.mouseX > this.width - player.width/2) {
    targetX = this.width - player.width;
   }
   else {
    targetX = this.mouseX - player.width/2;
   }
        
   player.x += (targetX/2 - player.x/2) / easing;   
}
      
private function moveEnemy(e:Event):void
{   
   var enemyTargetX:Number;
   enemyTargetX = ball.x - enemy.width / 2;
       
   if (enemyTargetX <= 0) {
    enemyTargetX = 0;
   }
   else if (enemyTargetX >= this.width - enemy.width / 2) {
    enemyTargetX = this.width - enemy.width / 2;
   }
      
   enemy.x += (enemyTargetX / 2 - enemy.x / 2) / easing;
}
    ]]>
   </mx:Script>
</mx:Application>

Компилим, играем.

B1z ©

Сообщение отредактировал B1zDelKin - Суббота, 23 Января 2010, 15:36
AssasinДата: Воскресенье, 24 Января 2010, 14:19 | Сообщение # 2
web-coder
Сейчас нет на сайте
Так как здесь больше про Флеш рассказываться, то перенес в раздел Adobe Flash.
sky_noobДата: Четверг, 04 Февраля 2010, 21:02 | Сообщение # 3
уже был
Сейчас нет на сайте
Спасибо за уроки) Этому зверю мячик забить нереально) smile
JohnJДата: Воскресенье, 06 Июня 2010, 20:26 | Сообщение # 4
участник
Сейчас нет на сайте
Благодарю за уроки.
Одно замечание:
По-моему такое
Code
  if (ball.x <= 0) {    
     xDir *= -1;  
    }  
    else if (ball.x >= this.width - ball.width/2) {  
     xDir *= -1;  
    }

красивее оформлять так:
Code
  if (ball.x <= 0 || ball.x >= this.width - ball.width/2) {    
     xDir *= -1;  
    }  

и т.п.
QWER56Дата: Четверг, 07 Июля 2011, 11:00 | Сообщение # 5
старожил
Сейчас нет на сайте
А у меня такое выдаёт:
Code
[Fault] exception, information=TypeError: Error #1009: Не удается вызвать свойство или метод со ссылкой на объект "null".


К чему бы это?


ConsMark - поисковик по интернет магазинам.

Сообщение отредактировал QWER56 - Четверг, 07 Июля 2011, 11:01
noTformaTДата: Четверг, 07 Июля 2011, 11:23 | Сообщение # 6
Ukrainian independent game developer
Сейчас нет на сайте
QWER56, переменная есть, только ее значение - null;
тоже самое что:
var a:MovieClip = null;
a.x = 10;
выдаст
exception, information=TypeError: Error #1009: Не удается вызвать свойство или метод со ссылкой на объект "null".


@noTformaT
reload2Дата: Воскресенье, 28 Августа 2011, 16:47 | Сообщение # 7
частый гость
Сейчас нет на сайте
Тема супер мне оч помогло!

Если я тебе помог поставь пожалуста мне +1 к репутации)
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг