Infinite Runner kind of thing

I am trying to make a code where planes are added to make a road. The camera follows the player, and when a ground plane reaches the center, a new one is added after it. When a ground plane reaches a certain point that is off the screen, it gets deleted.

Here’s my current code:

import bge

scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
cam = scene.active_camera
own = cont.owner
center = scene.objects["Center"]


if "groundList" not in own:
    own["groundList"] = []
    
while own["tap"] == False: #run once
    ground = scene.addObject("Ground", "GroundGen", 0)
    ground.worldPosition = center.worldPosition
    own["groundList"].append(ground) 
    own["tap"] = True    
else: #run always after that
    for obj in own["groundList"]:
        if obj.worldPosition.y <= center.worldPosition.y - 15.0: #remove obj when its not on screen anymore
            own["groundList"].remove(obj)
            obj.endObject()


        if obj.worldPosition.y <= center.worldPosition.y and len(own["groundList"]) < 2: #add a new ground when another one reaches the center 
            newGround = scene.addObject("Ground", "GroundGen", 0)
            own["groundList"].append(newGround)

The first plane added does what it needs to do, but the rest don’t do anything. Can anyone tell me why?

Attachments

ScrollTanks.blend (463 KB)

The “Center” object moves forward with the player, but the “GroundGen” object does not. Once the player moves past it, the ground objects are spawned behind the player and immediately removed. You should probably parent “GroundGen” to “Center” to achieve the effect you want.

Side Note: Most games that have some form of infinitely scrolling terrain will actually have the terrain move backwards and keep the player stationary instead of moving the player forward. This prevents you from running into issues with floating-point precision as the player moves very far from the world origin.

If you are looking for an endless runner basic setup, i have one for you here:

I knew it was some silly mistake!!! Anyway, thanks
Cotaks, I have looked at your infinite runner and it’s great, but I’d rather try making my own, so I can learn.

Cotaks, I have looked at your infinite runner and it’s great, but I’d rather try making my own, so I can learn.

That is the best way! anyway some advice, dont use a while loop, just put the code from the while loop into the ‘if “groundList” not in own:’
that already runs only once, so it can execute the other 1 timer coding as well.


import bge


scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
cam = scene.active_camera
own = cont.owner
center = scene.objects["Center"]




if "groundList" not in own:
    own["groundList"] = []
    ground = scene.addObject("Ground", "GroundGen", 0)
    ground.worldPosition = center.worldPosition
    own["groundList"].append(ground) 


for obj in own["groundList"]:
    if obj.worldPosition.y <= center.worldPosition.y - 15.0: #remove obj when its not on screen anymore
        own["groundList"].remove(obj)
        obj.endObject()


    if obj.worldPosition.y <= center.worldPosition.y and len(own["groundList"]) < 2: #add a new ground when another one reaches the center 
        newGround = scene.addObject("Ground", "GroundGen", 0)
        own["groundList"].append(newGround)

should run the same as with the heavy while loop.

Alright, it works and spawns the ground, but sometimes there’s a gap between two planes, sometimes there’s not, like there’s some kind of offset. I don’t understamd why this happens.

EDIT: I am just going to model the planes with an unnecessary edge which will clip through.

OK, after some work, I managed to make my player stay always in the center and move the ground instead to create the illusion of movement, but simple moving-or-stopped motion, accounting for the player’s rotation. However, I’m stuck with how I could make acceleration.
My current code:

import bge, math

cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()


player = cont.owner


w = cont.sensors["w"]
s = cont.sensors["s"]
a = cont.sensors["a"]
d = cont.sensors["d"]


speedLimit = 0.5
accel = 0.001
brake = 0.01


if "vel" not in player:
    player["vel"] = 0.1
    
angleZ = player.localOrientation.to_euler()[2]


#player rotation           
if a.positive:
    player.applyRotation([0.0, 0.0, 0.05], True)
            
if d.positive:
    player.applyRotation([0.0, 0.0, -0.05], True)
    
#ground control
for ground in scene.objects:
    if not "player" in ground: #player, camera, etc. have property "player", the rest do not
        if w.positive: 
            x, y = (math.sin(angleZ) * player["vel"], math.cos(angleZ) * -player["vel"])
            ground.applyMovement([x, y, 0.0], False) 
            
        if s.positive:
            x, y = (math.sin(angleZ) * player["vel"], math.cos(angleZ) * player["vel"])
            ground.applyMovement([-x, y, 0.0], False)

I made a (short) video on how it works:

I have seen acceleration with Motion actuators, but I can’t do that here as the new grounds will be added and old ones will be deleted.

I have solved the acceleration problem. :slight_smile:

But there is a new problem, which is a difference between two ground planes. It is not a “glitch”, but it should not happen.

My current code (with acceleration):

import bge, math

cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()


player = cont.owner


w = cont.sensors["w"]
s = cont.sensors["s"]
a = cont.sensors["a"]
d = cont.sensors["d"]


speedLimit = 0.5
accel = 0.001
brake = 0.01


if "vel" not in player:
    player["vel"] = 0.1
    
angleZ = player.localOrientation.to_euler()[2]


#player rotation           
if a.positive:
    if s.positive:
        player.applyRotation([0.0, 0.0, -0.05], True)
    else:
        player.applyRotation([0.0, 0.0, 0.05], True)
    
            
if d.positive:
    if s.positive:
        player.applyRotation([0.0, 0.0, 0.05], True)
    else:    
        player.applyRotation([0.0, 0.0, -0.05], True)
    
#ground control
for ground in scene.objects:
    if not "player" in ground: #player, camera, etc. have property "player", the rest do not
        if w.positive: 
            if player["vel"] <= speedLimit:
                player["vel"] += accel
            else:
                player["vel"] = speedLimit
                
            x, y = (math.sin(angleZ) * player["vel"], math.cos(angleZ) * -player["vel"])
            
        elif s.positive:
            if player["vel"] <= speedLimit:
                player["vel"] += accel
            else:
                player["vel"] = speedLimit
            
            x, y = (math.sin(angleZ) * -player["vel"], math.cos(angleZ) * player["vel"])
        
        else:
            player["vel"] = 0.0
            x, y = (0.0, 0.0)
            
        ground.applyMovement([x, y, 0.0], False)

Attachments


Nevermind, solved it and it works perfectly, except for the ground spawning, which sometimes has an offset.