Event, on_mouse_click

?A classic use of callbacks in Python (and other languages) is to assign events to UI elements.

In other words, a "callback" is a function that is called when something happens. That something can be called an "event" in programmer-speak.

In some popular 3D world building game, the player has a tool(?? , hammer is for deleting blocks), when you click some place, you can put a block there.

In CodeCraft, Game class has some methods we can use to make similar tools: hammer, when you click the mouse, you can put a block,( a column, or even a huge cube, a growing flower;) digger, click the mouse to remove a block.

CodeCraft can be more powerful. With construction click, we can put more than just a block, such as a column, huge cube or a growing flower to name a few. Basically we can build anything with just one click, anything you can design a function.

=====end

Highligth mouse position

Introduce game.highlight() Methods

game.highlight("target") shows highlighted frame lines around a solid block where the mouse locates;

game.highlight("adjacent")("air") highlights the 'air' block where the mouse points to(it's adjacent to a solid surface because mouse position can only be on a solid surface).

They are helpful to use together with the following events so we can see where the location is that we are going to perform some actions at.

highlight("target") can be paired with action like deleting a block, or changing a block highlight("air") this can be paired with actions like putting a block.

Event, on_mouse_click

?A classic use of callbacks in Python (and other languages) is to assign events to UI elements.

In other words, a "callback" is a function that is called when something happens. That something can be called an "event" in programmer-speak.

In some popular 3D world building game, the player has a tool(?? , hammer is for deleting blocks), when you click some place, you can put a block there. In CodeCraft, Game class defined a object method we can use to make a similar tool:

game.on_mouse_click(callback)

it indicates the event "When mouse clicked" in the 3D CodeCraft world, a callback function is called when this event happens.

game.on_mouse_click automatically provides the Position object of the mouse location to the callback function as Position argument. Let's show an example to help explain this

# CodeCraft Part I, setup
from codecraft import Game, Position

game = Game()
materials = game.materials

game.clear_console()

# Part II, your work

game.highlight("air")     # show an empty location(adjacent to a solid surface) where the mouse points to

# define a callback action
def put_brick(mouse_position):
    game.set_block(mouse_position, materials['brick'])      

# invoke the mouse_click event with the callback    
game.on_mouse_click(put_brick)

Run the above app and click enter the 3D world, move the mouse around chose a location when it's highlighted, then click the mouse, a brick block shows there right away.

Some words on mouse_position game.on_mouse_click(callback) automatically provides the mouse_position for it's callback function put_brick(mouse_position), we can add a line in put_brick to print out the mouse_position coordinates (use mp instead of mouse_position for less typing)

def put_brick(mp):
    game.set_block(mp, materials['brick'])
    print('(', mouse_p.x,',', mouse_p.y, ',', mouse_p.z, ')')

game.on_mouse_click(put_brick)

Run and move the mouse around, each time you click the mouse to build a brick block, the location coordinates will show in the console:

(2, 1, -9)
(2, 2, -9)
(6, 1, -20)
...

Since we can access the mouse position coordinates using mp.x, mp.y, mp.z, creativity arise, we can think of some complex actions then just put a brick, which is never possible in other 3D building games. Learn to be a game developer is more powerful than just being a player, you get to define the rules!

Put up a column instead of a block

#??? not working, no access to xyz of mouse_position
def put_column(mp):
    for i in range(5):
        game.set_block(mp, materials['quartz'])

# yes!
def put_column(mp):
    for j in range(5):
        game.set_block(Position(mp.x, (mp.y+j), mp.z), materials['quartz'])


game.on_mouse_click(put_column)

Ambition is growing, let's try to put up a wall and a solid cube on mouse click

# put_wall, not test yet
def put_wall(mp):
    for i in range(5):
        for j in range(5):
            block(mp.x+i, mp.y+j, mp.z, 'cobblestone')

# put_cube(mp)
def put_cube(mp):
    for i in range(5):
        for j in range(5):
            for z in range(5):
                block(mp.x+i, mp.y+j, mp.z+k, 'diamond')
            # game.set_block(Position(mp.x+i, mp.y+j, mp.z+k), materials['diamond'])

game.on_mouse_click(put_cube)

How about some flowers for fun! put_flower on mouse click

# flower
def put_flower(mp):
    for j in range(5):
        game.set_block(Position(mp.x+j%2, mp.y+j, mp.z), materials['wool_green'])
    game.set_block(Position(mp.x, mp.y+5, mp.z), materials['wool_pink'])
    game.set_block(Position(mp.x+1, mp.y+6, mp.z), materials['wool_pink'])                                                          
    game.set_block(Position(mp.x-1, mp.y+6, mp.z), materials['wool_pink'])                                                           
    game.set_block(Position(mp.x, mp.y+7, mp.z), materials['wool_pink'])  
    game.set_block(Position(mp.x, mp.y+6, mp.z), materials['wool_yellow'])

game.on_mouse_click(put_flower)
def put_poppy(mp):
  for j in range(5):
      game.set_block(Position(mp.x+j%2, mp.y+j, mp.z), materials['wool_green']) 
  for i in range(3):
      game.set_block(Position(mp.x-i, mp.y+5, mp.z), materials['wool_red'])
      game.set_block(Position(mp.x+i, mp.y+5, mp.z), materials['wool_red'])
      game.set_block(Position(mp.x-i, mp.y+9, mp.z), materials['wool_red'])
      game.set_block(Position(mp.x+i, mp.y+9, mp.z), materials['wool_red'])
  for j in range(5):
      game.set_block(Position(mp.x-2, mp.y+5+j, mp.z), materials['wool_red'])
      game.set_block(Position(mp.x+2, mp.y+5+j, mp.z), materials['wool_red'])


game.on_mouse_click(put_poppy)

put_hollowCube on mouse click Remember some complex structures we made back in Volume I, Chapter 5. I'll use the hollowCube as an example, upon clicking the mouse I like to put up a hollow cube at the location.

# block(x,y,z,material)

# barx,y,z
def bar_x(x,y,z,length, material):
    for i in range(x, (x+length)):
        block(i,y,z, material)
#3-13 bar_y
def bar_y(x,y,z,height, material):
    for j in range(y, (y+height)):
        block(x,j,z, material)

#3-12 bar_z
def bar_z(x,y,z,length, material):
    for k in range(z, (z+length)):
        block(x,y,k, material)

# hollowCube
def hollowCube(x,y,z,a,m):
    for j in [y,y+a-1]:
        for k in [z, z+a-1]:
            bar_x(x, j, k, a, m)
    for i in [x,x+a-1]:
        for k in [z, z+a-1]:
            bar_y(i, y, k, a, m)
    for j in [y,y+a-1]:
        for i in [x,x+a-1]:
            bar_z(i, j, z, a, m)

hollowCube(0,10,-10, 5,'wool_blue')   # test a cube

def put_hollowCube(mp):
    hollowCube(mp.x, mp.y, mp.z, 5, 'wool_red')

game.on_mouse_click(put_hollowCube)

Complex Events

((Complex event: mouse_click, timer, ))

on_mouse_click, a wood stem will grow taller and two green leaves appear on the top

game.highlight("air")

plant_grain(mp):
    for j in range(5):
        game.set_timer(j/2, block, mp.x, mp.y+j, mp.z, 'log_spruce')

    for i in range(3):
        game.set_timer(i+5, block, mp.x+i, mp.y+6+i, mp.z, 'wool_green')
        game.set_timer(i+5, block, mp.x-i, mp.y+6+i, mp.z, 'wool_green')

plant_grain(Position(5,1,-10))

game.on_mouse_click(plant_grain)

Delete Blocks

game.highlight("target") shows the block location the mouse points to. At the solid block location, we can two kinds of actions: digging or change the block into a different material(put another block)

Change an existing block into 'obsidian':

game.highlight("target")    # show the block location the mouse points to

# change block is the same as put_brick
def put_obsidian(mp):
    game.set_block(mp, materials['obsidian'])

game.on_mouse_click(put_obsidian)

Digging Tools

Digging is commonly used in other 3D games, they usually have tools that perform this action.

We can define a tool "digger"

Remember in chapter?? Dictionary lesson, we explained that block materials can be indicated by it's value, integer 0 indicates "air" block (empty block) in material dictionary. Let's use this feature to program a digging tool in CodeCraft.

# digger (delete a block on mouse click)
game.highlight("target")

def digger(mp):
    game.set_block(mp, 0)

game.on_mouse_click(digger)

Other power digging tools

# shovel, delete two blocks on one click
def shovel(mp):
    for i in range(2):
        digger(Position(mp.x+i, mp.y, mp.z))        

# axe, delete 2*2 blocks on one click make a 2D hole
def axe(mp):
    for i in range(2):
        for j in range(2):
            digger( Position(mp.x+i, mp.y+j, mp.z) )           

# swords, delete 3*3*3 blocks on one click making a 3D hole           
def swords(mp):
    for in range(-1,2):
        for j in range(-1,2):
            for k in range(3):
                digger( Position(mp.x+i, mp.y+j, mp.z-k) )       # attention, mp.z-k

(( idea TNT: put a red/yellow/red/black cube, then put a bigger lava cube(random size), then use swords to delete a cube (also random size? smaller than lava edge) in the middle

def lava_cube(mp):
    for i in range(-2,3):
        for j in range(-2,3):
            for k in range(4):
                game.set_block(Position(mp.x+i, mp.y+j, mp.z-k), materials['wool_red'])

# random size lave_cube2, find lava block
def lava_cube2(mp):
    for i in range(randint(-3,0), randint(0,3)):
        for j in range(randint(-2,0), randint(0,3)):
            for k in range(4):
                game.set_block(Position(mp.x+i, mp.y+j, mp.z-k), materials['wool_blue'])

def tnt(mp):
   game.set_timer(0.5, block, mp.x, mp.y, mp.z, 'wool_red')
   game.set_timer(1, block, mp.x, mp.y, mp.z, 'wool_yellow')
   game.set_timer(1.5, block, mp.x, mp.y, mp.z, 'wool_red')  
   game.set_timer(2, lava_cube, mp)
   game.set_timer(2.5, swords, mp)
game.on_mouse_click(tnt)

results matching ""

    No results matching ""