In the last article we created the first step of the game, building the foundation. In this article we will create the second step of the game, controlling the main character

The main character movement uses TWEEN as the animation engine

Since this is not an introduction to Tweenjs, I won’t mention the basics here, but feel free to leave a comment if you need to

This is a wrapped animation

const TWEEN = require("@tweenjs/tween.js");

export class Animate {
  tween
  constructor(mesh:any, e:any, t:number) {
    this.tween = new TWEEN.Tween(mesh.position)
    this.tween.to(e, t)
    this.tween.start()
  }
}

Copy the code

Very simple, starting with a vector3 vector and ending with a Vector3 vector

Calling the animation also requires updating the animation in the Render method

// Render (): void {this.animate() this.renderer.render(this.scene, this.camera); this.controls.update(); TWEEN.update(); }Copy the code

Control the main character animation

T:number = 5000 // The movement time of the protagonist decreases with the increase of height

 // Control the main character
leadHandle() {
  // Control movement
  const lead = this.leadCube
  // Start point of animation
  const start = lead.position
  let ex = lead.position.x
  let ez = lead.position.z
  ex = ex === this.size / 2 ? this.size / 2 : (Math.abs(ex) + this.offset)
  ez = ez === this.size / 2 ? this.size / 2 : (Math.abs(ez) + this.offset)
  // Animation end point
  const end = new THREE.Vector3(ex, start.y, ez)
  console.log(start, end)
  // Turn on the main character animation
  // The difficulty increases with each additional layer minus 100 milliseconds
  const t = Math.max(this.T - this.leadCount * 100.1000)
  this.tween = new Animate(this.leadCube, end, t)
}
Copy the code

Operational control

The game uses Spaces to control protagonist pauses and other actions

Listen for keyDown events

window.addEventListener('keydown'.this.leadStop.bind(this))
Copy the code

Protagonist stop event

// The main character stops
leadStop(event) {
  // Determine whether to click space
  if (event.keyCode === 32) {
    if (this.tween) {
      // Pause the animation
      this.tween.tween.stop()
      this.tween = null
      // Generate the next protagonist
      this.createlead()
    }
  }
}
Copy the code

So far the game looks like this

At present, the next character can only be generated after clicking the space, so there is also a need for the protagonist to finish the movement to regenerate the next protagonist

this.tween.tween.onComplete(this.leadOperation.bind(this))
Copy the code

LeadOperation method

// Process the main characters, including generating new main characters, cutting main characters, redrawing the base plate, etc
leadOperation(){
  // Generate the next protagonist
  this.createlead()
}
Copy the code

Later articles will cover crop features, free fall, game over, etc

InitGame currently complete code

const THREE = require("three");
import { createCube } from '.. /utils/tools'
import { getSize, getPosition } from '.. /utils/getBox'
// Introduce encapsulated animation
import { Animate } from '.. /utils/animate'

class CreateGame {
  scene: any
  floorCube: any // Initial baseboard
  floorGroup: any / / base plate group
  size: number = 30 // Main character width and length
  leadY: number = 5 // The height of the protagonist
  leadCount: number = 0 / / counter
  startPoint: number = 60 // The hero starts at x or z
  leadInterval: any = null / / loop
  leadCube: any = null / / the protagonist
  tween: any = null / / animation
  offset: number = 40 // The offset of the hero's starting and ending positions
  T:number = 500 // The hero's movement time decreases with height
  constructor(element: any) {
    this.scene = element.scene
    this.floorGroup = new THREE.Group()
    this.scene.add(this.floorGroup)
    this.initFloor()
    window.addEventListener('keydown'.this.leadStop.bind(this))}initFloor() {
    const w: number = this.size
    const h: number = 50
    const l: number = this.size
    const floorParams = {
      w: w,
      h: h,
      l: l,
      x: w / 2.y: h / 2.z: l / 2
    }
    this.floorCube = createCube(floorParams)
    this.floorGroup.add(this.floorCube)
    this.floorGroup.updateMatrix()
  }
  createlead() {
    const size = new THREE.Vector3()
    const mesh = this.floorGroup
    // Get the size
    getSize(mesh, size)
    const position = new THREE.Vector3()
    // The position of the backplane should be 0 by default
    getPosition(mesh, position)
    const gy = position.y // The Y value of the backplane
    const y = size.y + gy + this.leadY / 2 // The main character's Y value
    // Set the odd-th hero to come from the negative side of the z axis, and the even-th hero to come from the X axis
    // You need a hero counter, which can also be used to count scores
    // The starting point is 30 away from the base plate
    // The initial position of the main character
    const flag: boolean = this.leadCount % 2= = =0 // Is it even
    // start point of x
    let sx: number = (flag ? -this.startPoint - this.offset : 0) + this.size / 2
    // z start point
    let sz: number = (flag ? 0 : -this.startPoint - this.offset) + this.size / 2
    // Create a protagonist
    const leadParam = {
      w: this.size,
      h: this.leadY,
      l: this.size,
      x: sx,
      y,
      z: sz
    }
    this.leadCube = createCube(leadParam)
    this.floorGroup.add(this.leadCube)
    // After creating a role, the counter increases by 1
    this.leadCount++
    // Start controlling the main character
    // const startVector3 = new THREE.Vector3(sx,y,sz)
    this.leadHandle()
  }
  // Control the main character
  leadHandle():void {
    // Control movement
    const lead = this.leadCube
    // Start point of animation
    const start = lead.position
    let ex = lead.position.x
    let ez = lead.position.z
    ex = ex === this.size / 2 ? this.size / 2 : (Math.abs(ex) + this.offset)
    ez = ez === this.size / 2 ? this.size / 2 : (Math.abs(ez) + this.offset)
    // Animation end point
    const end = new THREE.Vector3(ex, start.y, ez)
    console.log(start, end)
    // Turn on the main character animation
    // The difficulty increases with each additional layer minus 100 milliseconds
    const t = Math.max(this.T - this.leadCount * 100.1000)
    this.tween = new Animate(this.leadCube, end, t)

    if(this.tween) {
      console.log(this.tween.tween)
      this.tween.tween.onComplete(this.leadOperation.bind(this))}}// The main character stops
  leadStop(event):void {
    // Determine whether to click space
    if (event.keyCode === 32) {
      if (this.tween) {
        // Pause the animation
        this.tween.tween.stop()
        this.tween = null
        this.leadOperation()
      }
    }
  }

  // Process the main characters, including generating new main characters, cutting main characters, redrawing the base plate, etc
  leadOperation(){
    // Generate the next protagonist
    this.createlead()
    
  }
}

export { CreateGame }
Copy the code

The code may be a little rough, please correct

3D stacking game – The first basic initialization game