summaryrefslogtreecommitdiffhomepage
path: root/samples/99_genre_fighting/01_special_move_inputs/app/main.rb
blob: 5db1951c2694ff5509c5671a02ff17805d2219c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
def tick args
  #tick_instructions args, "Use LEFT and RIGHT arrow keys to move and SPACE to jump."
  defaults args
  render args
  input args
  calc args
end

# sets default values and creates empty collections
# initialization only happens in the first frame
def defaults args
  fiddle args

  args.state.tick_count = args.state.tick_count
  args.state.bridge_top = 128
  args.state.player.x  ||= 0                        # initializes player's properties
  args.state.player.y  ||= args.state.bridge_top
  args.state.player.w  ||= 64
  args.state.player.h  ||= 64
  args.state.player.dy ||= 0
  args.state.player.dx ||= 0
  args.state.player.r  ||= 0
  args.state.game_over_at ||= 0
  args.state.animation_time ||=0

  args.state.timeleft ||=0
  args.state.timeright ||=0
  args.state.lastpush ||=0

  args.state.inputlist ||=  ["j","k","l"]
end

# sets enemy, player, hammer values
def fiddle args
  args.state.gravity                     = -0.5
  args.state.player_jump_power           = 10      # sets player values
  args.state.player_jump_power_duration  = 5
  args.state.player_max_run_speed        = 20
  args.state.player_speed_slowdown_rate  = 0.9
  args.state.player_acceleration         = 0.9
end

# outputs objects onto the screen
def render args
  if (args.state.player.dx < 0.01) && (args.state.player.dx > -0.01)
    args.state.player.dx = 0
  end

  #move list
  (args.layout.rect_group row: 0, col_from_right: 8, drow: 0.3,
                          merge: { vertical_alignment_enum: 0, size_enum: -2 },
                          group: [
                            { text: "move:             WASD" },
                            { text: "jump:             Space" },
                            { text: "attack forwards:  J (while on ground" },
                            { text: "attack upwards:   K (while on groud)" },
                            { text: "attack backwards: J (while on ground and holding A)" },
                            { text: "attack downwards: K (while in air)" },
                            { text: "dash attack:      J, K in quick succession." },
                            { text: "shield: hold      J, K at the same time." },
                            { text: "dash backwards:   A, A in quick succession." },
                          ]).into args.outputs.labels

  # registered moves
  args.outputs.labels << { x: 0.to_layout_col,
                           y: 0.to_layout_row,
                           text: "input history",
                           size_enum: -2,
                           vertical_alignment_enum: 0 }

  (args.state.inputlist.take(5)).map do |s|
    { text: s, size_enum: -2, vertical_alignment_enum: 0 }
  end.yield_self do |group|
    (args.layout.rect_group row: 0.3, col: 0, drow: 0.3, group: group).into args.outputs.labels
  end


  #sprites
  player = [args.state.player.x, args.state.player.y,
            args.state.player.w, args.state.player.h,
            "sprites/square/white.png",
            args.state.player.r]

  playershield = [args.state.player.x - 20, args.state.player.y - 10,
                  args.state.player.w + 20, args.state.player.h + 20,
                  "sprites/square/blue.png",
                  args.state.player.r,
                  0]

  playerjab = [args.state.player.x + 32, args.state.player.y,
               args.state.player.w, args.state.player.h,
               "sprites/isometric/indigo.png",
               args.state.player.r,
               0]

  playerupper = [args.state.player.x, args.state.player.y + 32,
                 args.state.player.w, args.state.player.h,
                 "sprites/isometric/indigo.png",
                 args.state.player.r+90,
                 0]

  if ((args.state.tick_count - args.state.lastpush) <= 15)
    if (args.state.inputlist[0] == "<<")
      player = [args.state.player.x, args.state.player.y,
                args.state.player.w, args.state.player.h,
                "sprites/square/yellow.png", args.state.player.r]
    end

    if (args.state.inputlist[0] == "shield")
      player = [args.state.player.x, args.state.player.y,
                args.state.player.w, args.state.player.h,
                "sprites/square/indigo.png", args.state.player.r]

      playershield = [args.state.player.x - 10, args.state.player.y - 10,
                      args.state.player.w + 20, args.state.player.h + 20,
                      "sprites/square/blue.png", args.state.player.r, 50]
    end

    if (args.state.inputlist[0] == "back-attack")
      playerjab = [args.state.player.x - 20, args.state.player.y,
                   args.state.player.w - 10, args.state.player.h,
                   "sprites/isometric/indigo.png", args.state.player.r, 255]
    end

    if (args.state.inputlist[0] == "forward-attack")
      playerjab = [args.state.player.x + 32, args.state.player.y,
                   args.state.player.w, args.state.player.h,
                   "sprites/isometric/indigo.png", args.state.player.r, 255]
    end

    if (args.state.inputlist[0] == "up-attack")
      playerupper = [args.state.player.x, args.state.player.y + 32,
                     args.state.player.w, args.state.player.h,
                     "sprites/isometric/indigo.png", args.state.player.r + 90, 255]
    end

    if (args.state.inputlist[0] == "dair")
      playerupper = [args.state.player.x, args.state.player.y - 32,
                     args.state.player.w, args.state.player.h,
                     "sprites/isometric/indigo.png", args.state.player.r + 90, 255]
    end

    if (args.state.inputlist[0] == "dash-attack")
      playerupper = [args.state.player.x, args.state.player.y + 32,
                     args.state.player.w, args.state.player.h,
                     "sprites/isometric/violet.png", args.state.player.r + 90, 255]

      playerjab = [args.state.player.x + 32, args.state.player.y,
                   args.state.player.w, args.state.player.h,
                   "sprites/isometric/violet.png", args.state.player.r, 255]
    end
  end

  args.outputs.sprites << playerjab
  args.outputs.sprites << playerupper
  args.outputs.sprites << player
  args.outputs.sprites << playershield

  args.outputs.solids << 20.map_with_index do |i| # uses 20 squares to form bridge
    [i * 64, args.state.bridge_top - 64, 64, 64]
  end
end

# Performs calculations to move objects on the screen
def calc args
  # Since velocity is the change in position, the change in x increases by dx. Same with y and dy.
  args.state.player.x  += args.state.player.dx
  args.state.player.y  += args.state.player.dy

  # Since acceleration is the change in velocity, the change in y (dy) increases every frame
  args.state.player.dy += args.state.gravity

  # player's y position is either current y position or y position of top of
  # bridge, whichever has a greater value
  # ensures that the player never goes below the bridge
  args.state.player.y  = args.state.player.y.greater(args.state.bridge_top)

  # player's x position is either the current x position or 0, whichever has a greater value
  # ensures that the player doesn't go too far left (out of the screen's scope)
  args.state.player.x  = args.state.player.x.greater(0)

  # player is not falling if it is located on the top of the bridge
  args.state.player.falling = false if args.state.player.y == args.state.bridge_top
  #args.state.player.rect = [args.state.player.x, args.state.player.y, args.state.player.h, args.state.player.w] # sets definition for player
end

# Resets the player by changing its properties back to the values they had at initialization
def reset_player args
  args.state.player.x = 0
  args.state.player.y = args.state.bridge_top
  args.state.player.dy = 0
  args.state.player.dx = 0
  args.state.enemy.hammers.clear # empties hammer collection
  args.state.enemy.hammer_queue.clear # empties hammer_queue
  args.state.game_over_at = args.state.tick_count # game_over_at set to current frame (or passage of time)
end

# Processes input from the user to move the player
def input args
  if args.state.inputlist.length > 5
    args.state.inputlist.pop
  end

  should_process_special_move = (args.inputs.keyboard.key_down.j)           ||
                                (args.inputs.keyboard.key_down.k)           ||
                                (args.inputs.keyboard.key_down.a)           ||
                                (args.inputs.keyboard.key_down.d)           ||
                                (args.inputs.controller_one.key_down.y)     ||
                                (args.inputs.controller_one.key_down.x)     ||
                                (args.inputs.controller_one.key_down.left)  ||
                                (args.inputs.controller_one.key_down.right)

  if (should_process_special_move)
    if (args.inputs.keyboard.key_down.j && args.inputs.keyboard.key_down.k) ||
       (args.inputs.controller_one.key_down.x && args.inputs.controller_one.key_down.y)
      args.state.inputlist.unshift("shield")
    elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y) &&
          (args.state.inputlist[0] == "forward-attack") && ((args.state.tick_count - args.state.lastpush) <= 15)
      args.state.inputlist.unshift("dash-attack")
      args.state.player.dx = 20
    elsif (args.inputs.keyboard.key_down.j && args.inputs.keyboard.a) ||
          (args.inputs.controller_one.key_down.x && args.inputs.controller_one.key_down.left)
      args.state.inputlist.unshift("back-attack")
    elsif ( args.inputs.controller_one.key_down.x || args.inputs.keyboard.key_down.j)
      args.state.inputlist.unshift("forward-attack")
    elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y) &&
          (args.state.player.y > 128)
      args.state.inputlist.unshift("dair")
    elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y)
      args.state.inputlist.unshift("up-attack")
    elsif (args.inputs.controller_one.key_down.left || args.inputs.keyboard.key_down.a) &&
          (args.state.inputlist[0] == "<") &&
          ((args.state.tick_count - args.state.lastpush) <= 10)
      args.state.inputlist.unshift("<<")
      args.state.player.dx = -15
    elsif (args.inputs.controller_one.key_down.left || args.inputs.keyboard.key_down.a)
      args.state.inputlist.unshift("<")
      args.state.timeleft = args.state.tick_count
    elsif (args.inputs.controller_one.key_down.right || args.inputs.keyboard.key_down.d)
      args.state.inputlist.unshift(">")
    end

    args.state.lastpush = args.state.tick_count
  end

  if args.inputs.keyboard.space || args.inputs.controller_one.r2   # if the user presses the space bar
    args.state.player.jumped_at ||= args.state.tick_count # jumped_at is set to current frame

    # if the time that has passed since the jump is less than the player's jump duration and
    # the player is not falling
    if args.state.player.jumped_at.elapsed_time < args.state.player_jump_power_duration && !args.state.player.falling
      args.state.player.dy = args.state.player_jump_power # change in y is set to power of player's jump
    end
  end

  # if the space bar is in the "up" state (or not being pressed down)
  if args.inputs.keyboard.key_up.space || args.inputs.controller_one.key_up.r2
    args.state.player.jumped_at = nil # jumped_at is empty
    args.state.player.falling = true # the player is falling
  end

  if args.inputs.left # if left key is pressed
    if args.state.player.dx < -5
      args.state.player.dx = args.state.player.dx
    else
      args.state.player.dx = -5
    end

  elsif args.inputs.right # if right key is pressed
    if args.state.player.dx > 5
      args.state.player.dx = args.state.player.dx
    else
      args.state.player.dx = 5
    end
  else
    args.state.player.dx *= args.state.player_speed_slowdown_rate # dx is scaled down
  end

  if ((args.state.player.dx).abs > 5) #&& ((args.state.tick_count - args.state.lastpush) <= 10)
    args.state.player.dx *= 0.95
  end
end

def tick_instructions args, text, y = 715
  return if args.state.key_event_occurred
  if args.inputs.mouse.click ||
     args.inputs.keyboard.directional_vector ||
     args.inputs.keyboard.key_down.enter ||
     args.inputs.keyboard.key_down.space ||
     args.inputs.keyboard.key_down.escape
    args.state.key_event_occurred = true
  end

  args.outputs.debug << [0, y - 50, 1280, 60].solid
  args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
  args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
end