融入动画技术的交互应用

本文介绍了一款结合向量运动、粒子特效和碰撞事件的交互式方块游戏开发。开发者受到游戏直播的启发,制作了一个包含7关的通关小游戏,详细解析了方块运动、碰撞处理和爆炸效果的实现,并分享了实验过程中的感悟。
摘要由CSDN通过智能技术生成

作业要求完成情况

  1. 向量的运动速度:方块的运动
  2. 粒子系统:方块爆炸后粒子特效
  3. 碰撞事件:方块之间的碰撞

代码详解

方块运动
 void move()
  {
    if (player != null && player.alive && canShoot && dist(player.position.x, player.position.y, position.x, position.y) <= sight/2)
    {
      inSight = true;

      if (player.position.x > position.x)
      {
        velocity.x = lerp(velocity.x, speed, 0.01);
      } else if (player.position.x < position.x)
      {
        velocity.x = lerp(velocity.x, -speed, 0.01);
      } else 
      {
        velocity.x = lerp(velocity.x, 0, 0.1);
      }

      if (player.position.y > position.y)
      {
        velocity.y = lerp(velocity.y, speed, 0.01);
      } else if (player.position.y < position.y)
      {
        velocity.y = lerp(velocity.y, -speed, 0.01);
      } else 
      {
        velocity.y = lerp(velocity.y, 0, 0.1);
      }
    } else
    {
      if (canShoot)
        cooldown = maxCoolDown;
      inSight = false;
      velocity.x += random(-0.1, 0.1);
      velocity.y += random(-0.1, 0.1);
    }
    velocity.limit(speed);
  }
碰撞实体
 int collides(Entity E)
  {
    if (this.ID != E.ID)
    {
      float A_top = this.position.y - this.dimentions.y/2;
      float A_right = this.position.x + this.dimentions.x/2;
      float A_bot = this.position.y + this.dimentions.y/2;
      float A_left = this.position.x - this.dimentions.x/2;
      
      float B_top = E.position.y - E.dimentions.y/2;
      float B_right = E.position.x + E.dimentions.x/2;
      float B_bot = E.position.y + E.dimentions.y/2;
      float B_left = E.position.x - E.dimentions.x/2;
      
      if(A_bot > B_top && A_left < B_right && A_right > B_left && this.position.y < B_top)
      {
        return 1;
      }
      if(A_left < B_right && A_top < B_bot && A_bot > B_top && this.position.x > B_right)
      {
        return 2;
      }
      if(A_top < B_bot && A_left < B_right && A_right > B_left && this.position.y > B_bot)
      {
        return 3;
      }
      if(A_right > B_left && A_top < B_bot && A_bot > B_top && this.position.x < B_left)
      {
        return 4;
      }
      
    }
    return -1;
  }
碰撞处理
void handleCollision()
{

  for (Entity E : walls) 
  {
    if (player.alive && player.collides(E) != -1)
    {
      switch(player.collides(E))
      {
      case 1:
        player.velocity.y = 0;
        player.position.y -= 2;
        break;
      case 2:
        player.velocity.x = 0;
        player.position.x += 2;
        break;
      case 3:
        player.velocity.y = 0;
        player.position.y += 2;
        break;
      case 4:
        player.velocity.x = 0;
        player.position.x -= 2;
        break;
      }
    }
    for (Entity EN : enemies) 
    {
      if (EN.collides(E) != -1)
      {
        switch(EN.collides(E))
        {
        case 1:
          EN.velocity.y *= -1;
          EN.position.y -= 1;
          break;
        case 2:
          EN.velocity.x *= -1;
          EN.position.x += 1;
          break;
        case 3:
          EN.velocity.y *= -1;
          EN.position.y += 1;
          break;
        case 4:
          EN.velocity.x *= -1;
          EN.position.x -= 1;
          break;
        }
      }
    }
    for (int i = bullets.size() - 1; i >= 0; i--)
    {
      if (E.special == -1 && bullets.get(i).collides(E) != -1)
      {
        bullets.get(i).onRemoval();
        bullets.remove(i);
        continue;
      } else if (E.special == 2 && bullets.get(i).collides(E) != -1)
      {
        switch(bullets.get(i).collides(E))
        {
        case 1:
          bullets.get(i).velocity.y *= -1;
          bullets.get(i).position.y -= 2;
          break;
        case 2:
          bullets.get(i).velocity.x *= -1;
          bullets.get(i).position.x += 2;
          break;
        case 3:
          bullets.get(i).velocity.y *= -1;
          bullets.get(i).position.y += 2;
          break;
        case 4:
          bullets.get(i).velocity.x *= -1;
          bullets.get(i).position.x -= 2;
          break;
        }
      }  
      if (player.alive && bullets.get(i).collides(player) != -1)
      {
        bullets.remove(i);
        player.lives--;
      }
    }
  }
爆炸处理
 if (player.lives <= 0)
  {
    player.alive = false;
    player.lives = 1;
    player.velocity.setMag(1);
    for (int i = 0; i < 25; i++)
    {
      Entity P = new Entity(player.position.x, player.position.y);
      P.dimentions.x = 5;
      P.dimentions.y = 5;
      P.filler = player.filler;
      P.velocity.x = random(-2, 2);
      P.velocity.y = random(-2, 2);
      P.velocity.add(player.velocity);
      particles.add(P);
    }
  }

  if (player.alive) {
    for (int i = enemies.size()-1; i >= 0; i--)
    {
      if (player.collides(enemies.get(i)) != -1)
      {
        if (enemies.get(i).parent != null)
          enemies.get(i).parent.children.remove(enemies.get(i));
        enemies.remove(i);
      }
    }
  }
}
关卡设置

void loadWalls(int levels)
{
  switch(levels)
  {
  case 0:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/4, stage.Height/2);
    enemies.add(new Enemy(stage.Width*3/4, stage.Height/2));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/2, stage.Height/2, 20, stage.Height*2/3, -1));
    break;
    
  case 1:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/4, stage.Height/2);
    enemies.add(new Enemy(stage.Width*3/4, stage.Height*1/4));
    enemies.add(new Enemy(stage.Width*3/4, stage.Height*3/4));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/2, stage.Height/2, 20, stage.Height*2/3, -1));
    break;
   
  case 2:
   stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/4, stage.Height/2);
    enemies.add(new Enemy(stage.Width*3/4, stage.Height/4));
    enemies.add(new Enemy(stage.Width*3/4, stage.Height*3/4));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/2, stage.Height/2, 20, stage.Height*2/3, -1));
    walls.add(new Wall(stage.Width*3/4, stage.Height/2, stage.Width/2, 20, 1));
    break;
    
  case 3:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/4, stage.Height/2);
    enemies.add(new Enemy(stage.Width*2/3, stage.Height/4));
    enemies.add(new Enemy(stage.Width*5/6, stage.Height/4));
    enemies.add(new Trio(stage.Width*2/3, stage.Height*3/4));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/2, stage.Height/2, 20, stage.Height*2/3, -1));
    walls.add(new Wall(stage.Width*3/4, stage.Height/2, stage.Width/2, 20, 1));
    break;
  case 4:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/2, stage.Height/2);
    enemies.add(new Enemy(stage.Width/8, stage.Height/4));
    enemies.add(new Enemy(stage.Width/8, stage.Height*3/4));
    enemies.add(new Enemy(stage.Width*7/8, stage.Height/4));
    enemies.add(new Enemy(stage.Width*7/8, stage.Height*3/4));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/4, stage.Height/2, 20, stage.Height*3/4, 1));
    walls.add(new Wall(stage.Width*3/4, stage.Height/2, 20, stage.Height*3/4, 1));
    walls.add(new Wall(stage.Width/8, stage.Height/2, stage.Width/4, 20, 1));
    walls.add(new Wall(stage.Width*7/8, stage.Height/2, stage.Width/4, 20, 1));
    break;
  case 5:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/2, stage.Height/2);
    enemies.add(new Enemy(stage.Width/8, stage.Height/4));
    enemies.add(new Trio(stage.Width/8, stage.Height*3/4));
    enemies.add(new Trio(stage.Width*7/8, stage.Height/4));
    enemies.add(new Enemy(stage.Width*7/8, stage.Height*3/4));
    enemies.add(new Enemy(stage.Width/2, stage.Height*7/8));
    edges(stage.Width, stage.Height);
    walls.add(new Wall(stage.Width/4, stage.Height/2, 20, stage.Height*3/4, 1));
    walls.add(new Wall(stage.Width*3/4, stage.Height/2, 20, stage.Height*3/4, -1));
    walls.add(new Wall(stage.Width/8, stage.Height/2, stage.Width/4, 20, 2));
    walls.add(new Wall(stage.Width*7/8, stage.Height/2, stage.Width/4, 20, 1));
    walls.add(new Wall(stage.Width/2, stage.Height/4, stage.Width/4, 50, 2));
    walls.add(new Wall(stage.Width/2, stage.Height*3/4, stage.Width/4, 50, 1));
    break;
  case 6:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/8, stage.Height/2);
    enemies.add(new Mother(stage.Width/2, stage.Height/2));
    enemies.add(new Trio(stage.Width*3/4, stage.Height/2));
    enemies.add(new Enemy(stage.Width*3/4, stage.Height/10));
    enemies.add(new Enemy(stage.Width*3/4, stage.Height*9/10));
    edges(stage.Width, stage.Height);
    walls.add( new Wall(stage.Width/4, stage.Height/2, 20, stage.Height/2 + 20, 1));
    walls.add( new Wall(stage.Width/2, stage.Height/4, stage.Width/2 + 20, 20, 1));
    walls.add( new Wall(stage.Width/2, stage.Height*3/4, stage.Width/2 + 20, 20, 1));
    break;
  case 7:
    stage.Width = 800;
    stage.Height = 600;
    player = new Player(stage.Width/8, stage.Height/2);
    enemies.add(new Trio(stage.Width/2, stage.Height/2));
    enemies.add(new SlowEnemy(stage.Width*3/4, stage.Height/2));
    enemies.add(new SlowEnemy(stage.Width*3/4, stage.Height/10));
    enemies.add(new SlowEnemy(stage.Width*3/4, stage.Height*9/10));
    edges(stage.Width, stage.Height);
    walls.add( new Wall(stage.Width/4, stage.Height/2, 20, stage.Height/2 + 20, 1));
    walls.add( new Wall(stage.Width/2, stage.Height/4, stage.Width/2 + 20, 20, 1));
    walls.add( new Wall(stage.Width/2, stage.Height*3/4, stage.Width/2 + 20, 20, 1));
    break;
 
  default:
    stage.level = 0;
    loadWalls(0);
    break;
  }
}

实验效果截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验感悟

平时偶尔会看一些游戏区的主播进行游戏直播,其中一些看似画面简单但难度却爆炸的小游戏给我留下了很深刻的印象,于是便打算仿照制作一款类似的通关类的动作小游戏。
贪吃方块游戏参考了 代码本色 中的相关动画技术,其中包括第一章的向量,第四章的粒子,以及第五章的碰撞事件。在游戏关卡方面我只制作了七道关卡,但自己连第五关都过不了,这还是在我把前几关设置的比较容易的基础上,实在汗颜,或许我就是个手残党。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值