2
$\begingroup$

I'm trying to create a simple golf putt game using the Blender Game Engine as depicted here:

enter image description here

The problem is that the ball doesn't roll straight. If I launch the ball at about 5 degrees left-of-center, I'd expect it to stay on that path until it hits the hole or falls off the board. Instead it takes a curved "S"-shaped path, apparently affected by the wires that can be seen when rendering the board material as wire.

The problem goes away if I don't cut the hole in the board, apparently because the wires are not present.

Below is a complete script that reproduces the problem. I'm using Blender 2.76 on Mac OS X and running the script at startup using "./blender.app/Contents/MacOS/blender myscript.py". The problem also occurs for other versions including 2.72, 2.73 and 2.75.

The .blend file resulting from the script below is available here: https://www.dropbox.com/s/wvwulkjq16au3rw/ball_roll_problem_v276.blend?dl=0
Just press the spacebar after starting the game to launch the ball, and you should see that it follows an "S" path rather than rolling straight.

An updated .blend file with improved mesh is available here: https://www.dropbox.com/s/vvyb7kkvtk11u3g/ball_roll_problem_v276_remeshed.blend?dl=0
The improved mesh helps the problem, but the ball still doesn't roll straight; the wires surrounding the hole still cause it to follow an "S" path.

Is there a way I can get the ball to roll straight? Any help would be most appreciated!

import bpy
import inspect
from math import radians



#(0) Initialize:
bpy.context.window.screen = bpy.data.screens['Game Logic']
scene      = bpy.data.scenes[0]
scene.render.engine = 'BLENDER_GAME'



#(1) Create a board using existing cube:
board          = bpy.data.objects['Cube']
board.name     = 'Board'
board.scale    = 2, 7, 0.1
board.location = 0, 0, -0.1
### cut a hole using boolean difference:
bpy.ops.mesh.primitive_cylinder_add( radius=0.4, location=(0,3,0) )
cylinder           = scene.objects[0]
modifier           = board.modifiers.new('hole_cutter', 'BOOLEAN')
modifier.object    = cylinder
modifier.operation = 'DIFFERENCE'
### apply the modifier:
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = board
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="hole_cutter")
scene.objects.unlink(cylinder)



#(2) Add a ball:
bpy.ops.mesh.primitive_uv_sphere_add(size=0.1, location=(0, -6, 0.1))
ball       = scene.objects[0]
ball.name  = 'Ball'
### game settings:
ball.game.physics_type = 'RIGID_BODY'
ball.game.use_collision_bounds = True
ball.game.collision_margin = 0
ball.game.collision_bounds_type = 'SPHERE'
ball.game.mass         = 1
ball.game.radius       = 0.1
### game properties:
bpy.ops.object.game_property_new(type='BOOL', name='launched')
ball.game.properties['launched'].value = False
### add controller:
bpy.context.scene.objects.active = ball
bpy.ops.logic.sensor_add(type='ALWAYS')
bpy.ops.logic.controller_add(type='PYTHON')
sensor      = ball.game.sensors[-1]
controller  = ball.game.controllers[-1]
sensor.use_pulse_true_level = True
sensor.link(controller)
### add controller script:
def my_ball_controller():
    import bge
    scene       = bge.logic.getCurrentScene()
    ball        = scene.objects['Ball']
    SPACE_key   = bge.logic.KX_INPUT_ACTIVE == bge.logic.keyboard.events[ bge.events.SPACEKEY ]
    if SPACE_key and not ball['launched']:
        ball.applyForce((-30, 300, 0), 0)
        ball['launched'] = True
bpy.data.texts.new('my_ball_controller')
script          = bpy.data.texts['my_ball_controller']
controller.text = script
lines           = inspect.getsourcelines( my_ball_controller )[0]
for line in lines[1:]:
    script.write( line[1:] )



#(3) Set camera location:
camera  = bpy.data.objects['Camera']
camera.location       = (0, -12, 3)
camera.rotation_euler = (radians(70), 0, 0)
### set camera view:
for screen in bpy.data.screens[3:5]:
    for area in screen.areas:
        if area.type == 'VIEW_3D':
            for space in area.spaces:
                space.region_3d.view_perspective = 'CAMERA'
$\endgroup$
4
  • $\begingroup$ Hmmm, I ran the script with no issues. Strange. $\endgroup$
    – hawkenfox
    Commented Jan 7, 2016 at 8:04
  • $\begingroup$ I noticed that sometimes binary hole cutting yields material wires on the opposite side (the right side from the camera's perspective). I wonder if you've also tried launching the ball to the right using, for example: "ball.applyForce( (+30, 300, 0), 0)" ? $\endgroup$
    – ToddP
    Commented Jan 7, 2016 at 21:46
  • 1
    $\begingroup$ The Game Engines API is bge. The Blender API is bpy. You better do not mix Blender API and BGE API in one piece of code. The Blender API will not be available when running the game outside of Blender. Object changing operations will not take effect during the game run. I suggest to offer a blend file download rather than a generator script. $\endgroup$
    – Monster
    Commented Jan 8, 2016 at 4:30
  • $\begingroup$ Understood, I'll upload the .blend file momentarily... $\endgroup$
    – ToddP
    Commented Jan 8, 2016 at 11:32

1 Answer 1

1
$\begingroup$

As you have noted the mesh is the issue , switch to wireframe view and launch the BGE to see how it get triangulated ( combined with some rounding errors ) it will cause the deviation of the ball.

To avoid that you have to add either a Subsurf modifier ( in simple mode ) or a Remesh modifier ( in sharp mode ) and apply it before adding the Boolean modifier this will limit the bad triangulation inside a small area ( all the mesh are triangulated when passed to the BGE)

#(1) Create a board using existing cube:
....
### add and apply subsurf 
modifier           = board.modifiers.new('subsurf', 'SUBSURF')
modifier.levels    = 2
modifier.subdivision_type = 'SIMPLE'
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = board
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="subsurf")

### cut a hole using boolean difference:
....
$\endgroup$
3
  • $\begingroup$ Thanks very much for the suggestion! That certainly improves the mesh, but the ball still doesn't roll straight. When it gets near the hole the wires still cause its path to deviate. The updated .blend file is available here: https://www.dropbox.com/s/vvyb7kkvtk11u3g/ball_roll_problem_v276_remeshed.blend?dl=0 $\endgroup$
    – ToddP
    Commented Jan 8, 2016 at 23:58
  • $\begingroup$ @tdoe at the moment i think you should find a better way for creating the board experiment with higher subdivision levels or try other methods $\endgroup$
    – Chebhou
    Commented Jan 10, 2016 at 10:12
  • $\begingroup$ Are there any methods in particular you would recommend? I've tried triangular mesh collision bounds, for example, but the problem is even worse: ball roll is strongly affected by the mesh. $\endgroup$
    – ToddP
    Commented Jan 10, 2016 at 23:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .