/
game.asm
2279 lines (2034 loc) · 54.4 KB
/
game.asm
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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#####################################################################
#
# CSC258 Summer 2021 Assembly Final Project
# University of Toronto
#
# Student: Matthew Zhu, 1006209103, zhumatt2
#
# Bitmap Display Configuration:
# -Unit width in pixels: 4
# -Unit height in pixels: 4
# -Display width in pixels: 512
# -Display height in pixels: 256
# -Base Address for Display: 0x10008000 ($gp)
#
# Which milestones have been reached in this submission?
# (See the assignment handout for descriptions of the milestones)
# - All milestones have been reached
#
# Which approved features have been implemented for milestone 3?
# (See the assignment handout for the list of additional features)
# 1. Different levels - a total of 7 levels. Each level is progressively harder with more obstacles/enemies than the last, sometimes even getting new types of enemies
# 2. Increase in difficulty as the game progresses, including a gradual increase in number of enemies and new types of enemies appear.
# 3. Ship Abilities: The ship can change forms, and each form has both a passive ability and an ultimate ability that the player can activate to assist in survival
# 4. Enemy ships: Alongside the Asteroid obstacles, there are two types of enemy ships: the Berserker that has erratic, random movement, and the Hunter that tracks and moves towards the player's ship
# 5. Shoot obstacles/enemy ships: the ship has a laser cannon attached that allows the ship to shoot laser beams to destroy obstacles/enemies
#
#
# Link to video demonstration for final submission:
# - https://www.youtube.com/watch?v=IFddUS0m104
#
# Are you OK with us sharing the video with people outside course staff?
# - Yes
#
# Any additional information that the TA needs to know:
# While this file seems very large, I would say about half the lines of code are dedicated to just drawing the HUD (HP and Energy Bar sections) and GAME OVER screens.
# - See attached README file for a more in-depth explanation of abilities and controls. Basic controls are outlined as follows:
# w - Move Up
# a - Move Left
# s - Move Down
# d - Move Right
# p - Restart Game
# Spacebar - Shoot
# 1 - Switch to Blue Form
# 2 - Switch to Red Form
# 3 - Switch to Yellow Form
# x - Activate ship's active ability
######################################################################
.data
displayAddress: .word 0x10008000
blue: .word 0x2c85ff # stores the blue colour code
red: .word 0xe81515 # stores the red colour code
white: .word 0xffffff # stores the white colour code
black: .word 0x000000 # stores the black colour code
gray: .word 0x696969 # stores the gray colour code
purple: .word 0x9316cd # stores the purple colour code
yellow: .word 0xffbf00 # stores the yellow colour code
energyBlue: .word 0x009ACD # stores special blue color for the energy bar
obstacles: .word 0:10 # can have up to 10 obstacles
speeds: .word 0:10 # maximum 10 obstacles means 10 speeds
otherAddresses: .word 0:3 # Stores other addresses, namely the ship's laser, health bar address, and energy bar address in that order
gameCounter: .word 0x000000 # Tells game when to increase difficulty
shipAddress: .word 0x10008000
xCoordinate: .word 0x00000
yCoordinate: .word 0x0000c
absoluteZeroState: .word 0x000000 # 1 if special ability Absolute Zero is active, 0 if not
absoluteZeroCounter: .word 0x000000 # Determines how long to stay in Absolute Zero mode
shipHitBoxes: .word 0, 8, 40, 48, 1044, 1540, 1552, 1568, 1588, 2068, 3072, 3080, 3108, 3120
.text
lw $s0, displayAddress # $s0 stores the base address for display, immutable
INITIALIZE:
lw $a0, black
jal ERASE_ALL # Clear screen
jal DRAW_HUD # Draw the HUD with full HP Bar and empty energy bar
lw $t0, displayAddress # Initialize ship's address at start of game
addi $t0, $t0, 6144 # ship starts on 12th row, so 512*12=6144
sw $t0, shipAddress
addi $t1, $0, 0 # store current x-coordinate of ship
addi $t2, $0, 12 # store current y-coordinate of ship
sw $t1, xCoordinate
sw $t2, yCoordinate
addi $s5, $0, 3 # Store max enemies at a time in $s5, start game with 3 enemies maximum
lw $t3, gameCounter
addi $t3, $0, 0 # Set game counter to 0.
sw $t3, gameCounter
la $s1, obstacles # load array of obstacles into $s1
la $s2, speeds # load array of obstacle speeds into $s2
la $s6, otherAddresses # load array of other addresses (laser, HP bar, energy bar) into $s6
# Initialize values for the otherAddress array
addi $t6, $s6, 0 # Get address of first index in 'otherAddresses'
addi $t7, $0, 0
sw $t7, ($t6) # Reset the laser address to 0 since no lasers on initialiation
addi $t6, $s6, 4 # Get address of second index of 'otherAddresses'
addi $t7, $s0, 29988 # This is the address of full HP Bar
sw $t7, ($t6) # Store address of HP Bar in the second index of 'otherAddresses'
addi $t6, $s6, 8 # This is the address of third index of 'otherAddresses'
addi $t7, $s0, 30060 # This is address of an empty Energy Bar
sw $t7, ($t6) # Store address of Energy bar in the third index of 'otherAddresses'
addi $s3, $0, 2 # Store speed of plane in $s3, initialize speed of plane to 2
addi $s4, $0, 0 # Store number of enemies on the screen in $s4, start of game has 0 enemies on the screen
addi $s7, $0, 0 # Store ship's form in $s7, default ship form is ICE/Blue form (1=Blue, 2=Red, 3=Yellow)
jal resetArray # Reset our obstacles array in case we have existing values
Start:
lw $a0, black
lw $a1, black
jal drawShip # Erase Ship since parameters are both the color of 'black'
# Check for user input
li $t9, 0xffff0000
lw $t8, 0($t9)
beq $t8, 1, checkWhichInput
keyPressed: # Come here after doing the respective key action
jal checkShipForm # Update ship's form/color if needed
add $a0, $v0, $0 # Put the appropriate ship color into $a0
lw $a1, white
jal drawShip # Redraw the ship with updated position or color
# If current number of enemies equal (or greater which shouldn't be possible, skip spawning a new enemy.
bge $s4, $s5, enemiesCappedOut
# Here we confirmed we're adding an enemy, so let's get its spawn location
jal getNewEnemyLocation
add $a0, $v0, $0
jal addNewEnemy # Add new enemy to the 'obstacle' array, and add its corresponding speed to the 'speeds' array in parallel
enemiesCappedOut: # Don't bother spawning anything, max obstacles reached already
lw $a0, black
lw $a1, black
lw $t0, absoluteZeroState # Check if game is in Absolute Zero (special ability) state
beq $t0, 1, obstaclesFrozen
jal drawObstacles # Erase obstacles in the current positions
jal moveObstacles # Move obstacles to new position
lw $a0, gray
lw $a1, red
jal drawObstacles # Redraw obstacles our obstacles
obstaclesFrozen:
jal sustainAbsoluteZero # Check if Absolute Zero should still be active or not
lw $a0, black
lw $a1, black
jal despawnObstacles # Despawn obstacles that reach left of screen, got shot, or collided with ship
lw $a1, black
jal drawLaser # If a laser is present, erase it from the current position
jal moveLaser # Move the laser to its new position
lw $a0, red
jal drawLaser # Redraw the laser in its new position
# Check for collisions with laser
addi $t5, $s6, 0
lw $t8, ($t5)
beq $t8, 0, skipCheckingLaserCollisions # Skip checking laser collisions if no laser is present
jal checkLaserCollisions # Check laser collisions
skipCheckingLaserCollisions:
jal checkShipCollisions # Check if ship has collided with any obstacle/enemy
lw $a0, black
jal despawnLaser # Despawn laser if it reached the right end of the screen, or collided with an obstacle
jal levelCheck # Check if player has survived long enough to advance to a harder difficulty
addi $t7, $0, 30 # This is the number of game cycles it will take to charge the energy bar 1 unit
lw $t3, gameCounter
div $t3, $t7
mfhi $t7
bnez $t7, doNotCharge
bne $s7, $0, singleCharge # If not equal to 0, then not in blue form and we only do a single energy charge
jal chargeEnergy # Charge an extra time if in blue form
singleCharge:
jal chargeEnergy # Charge the energy bar as per usual
doNotCharge:
li $v0, 32
li $a0, 40 # Sleep
syscall
j Start
DONE:
tryAgainLoop:
# Check for user input
li $t9, 0xffff0000
lw $t8, 0($t9)
beq $t8, 1, checkForP # Check if user inputted 'p'
j tryAgainLoop
checkForP: # If user inputs 'p', restart the game
lw $t6, 4($t9)
beq $t6, 0x70, eraseAndRestart
beq $t6, 0x78, Exit # If user inputs 'x', exit the game
j tryAgainLoop
Exit:
li $v0, 10 # terminate the program gracefully
syscall
checkWhichInput:
lw $t6, 4($t9)
beq $t6, 0x61, boundedLeft # Move Left with 'a'
beq $t6, 0x64, boundedRight # Move Right with 'd'
beq $t6, 0x77, boundedAbove # Move Up with 'w'
beq $t6, 0x73, boundedBelow # Move Down with 's'
beq $t6, 0x20, shoot # Shoot Laser with spacebar
beq $t6, 0x70, eraseAndRestart # Restart the game with 'p'
beq $t6, 0x31, changeToBlue # Change to blue form with '1'
beq $t6, 0x32, changeToRed # Change to red form with '2'
beq $t6, 0x33, changeToYellow # Change to yellow form with '3'
beq $t6, 0x78, specialAbility # Activate special ability with 'x'
j keyPressed
specialAbility:
addi $t5, $s6, 8 # Get index for Energy Bar element in 'otherAddresses'
lw $t8, ($t5) # Get address of current Energy bar and store it in $t8
bne $t8, 1, notFullyCharged # If energy bar not full, skip all this and don't activate ability
beq $s7, 0, absoluteZero # If ship is blue form, use Absolute Zero
beq $s7, 1, solarFlare # If ship is red form, use Solar Flare
beq $s7, 2, blink # If ship is yellow form, use Blink!
notFullyCharged:
j keyPressed
absoluteZero: # Freezes all enemies
addi $t9, $0, 1
sw $t9, absoluteZeroState # Switch Absolute Zero state on
addi $t9, $s0, 30060 # Reset energy bar to 0
jal eraseEnergyBar
sw $t9, ($t5) # Get address of current Energy bar and store it in $t8
j keyPressed
sustainAbsoluteZero: # Function that automatically deactivates Absolute Zero after it's reached its time duration
lw $t0, absoluteZeroState
beq $t0, 1, chargeAbsoluteZero # If 1, charge. If 0, don't need to do anything
jr $ra
chargeAbsoluteZero:
lw $t1, absoluteZeroCounter # Increase counter for how long Absolute Zero has been active
addi $t1, $t1, 1
sw $t1, absoluteZeroCounter
beq $t1, 50, turnOffAbsoluteZero # If Abs. Zero counter is 50, then turn it off and reset the counter to 0
jr $ra
turnOffAbsoluteZero:
addi $t0, $0, 0
sw $t0, absoluteZeroState
sw $t0, absoluteZeroCounter
jr $ra
solarFlare: # Destroys all enemies
lw $a0, black
lw $a1, black
jal drawObstacles
jal resetArray
addi $t9, $s0, 30060 # Reset energy bar to 0
jal eraseEnergyBar
addi $t5, $s6, 8 # Get index for Energy Bar element in 'otherAddresses'
sw $t9, ($t5) # Get address of current Energy bar and store it in $t8
j keyPressed
blink: # Player teleports about half of the screen to the right, or less if there's not enough screen space to the right
lw $t1, xCoordinate
bge $t1, 64, tooFarForward # If player is too far to the right already, ability wil not activate
addi $t1, $t1, 48
sw $t1, xCoordinate # Update x-coordinates of ship
lw $t0, shipAddress
addi $t0, $t0, 192
sw $t0, shipAddress
addi $t9, $s0, 30060 # Reset energy bar to 0
jal eraseEnergyBar
sw $t9, ($t5) # Get address of current Energy bar and store it in $t8
tooFarForward:
j keyPressed
changeToBlue:
add $s7, $0, 0 # Switch ship form to Blue
j keyPressed
changeToRed:
lw $t0, absoluteZeroState # If Absolute Zero is not active, switch to Red form
beq $t0, 1, noRedChange
add $s7, $0, 1
noRedChange:
j keyPressed
changeToYellow:
lw $t0, absoluteZeroState # If Absolute Zero is not active, switch to Yellow form
beq $t0, 1, noYellowChange
add $s7, $0, 2
noYellowChange:
j keyPressed
eraseAndRestart:
j INITIALIZE
boundedBelow: # Make sure ship doesn't go down off the screen
addi $t8, $0, 47
sub $t8, $t8, $s3
lw $t2, yCoordinate
ble $t2, $t8, moveDown
j keyPressed
boundedAbove: # Make sure ship doesn't go up off the screen
addi $t8, $0, 0
add $t8, $t8, $s3
lw $t2, yCoordinate
bge $t2, $t8, moveUp
j keyPressed
boundedLeft: # Make sure ship doesn't go left off the screen
addi $t8, $0, 0
add $t8, $t8, $s3
lw $t1, xCoordinate
bge $t1, $t8, moveLeft
j keyPressed
boundedRight: # Make sure ship doesn't go right off the screen
addi $t8, $0, 113
sub $t8, $t8, $s3
lw $t1, xCoordinate
ble $t1, $t8, moveRight
j keyPressed
moveDown: # Makes ship go down while updating all required coordinates
addi $t8, $0, 512
mult $s3, $t8
mflo $t7
lw $t0, shipAddress
add $t0, $t0, $t7
sw $t0, shipAddress
lw $t2, yCoordinate
add $t2, $t2, $s3
sw $t2, yCoordinate
j keyPressed
moveUp: # Makes ship go up while updating all required coordinates
addi $t8, $0, -512
mult $s3, $t8
mflo $t7
lw $t0, shipAddress
add $t0, $t0, $t7
sw $t0, shipAddress
lw $t2, yCoordinate
sub $t2, $t2, $s3
sw $t2, yCoordinate
j keyPressed
moveRight: # Makes ship go right while updating all required coordinates
addi $t8, $0, 4
mult $s3, $t8
mflo $t7
lw $t0, shipAddress
add $t0, $t0, $t7
sw $t0, shipAddress
lw $t1, xCoordinate
add $t1, $t1, $s3
sw $t1, xCoordinate
j keyPressed
moveLeft: # Makes ship go left while updating all required coordinates
addi $t8, $0, -4
mult $s3, $t8
mflo $t7
lw $t0, shipAddress
add $t0, $t0, $t7
sw $t0, shipAddress
lw $t1, xCoordinate
sub $t1, $t1, $s3
sw $t1, xCoordinate
j keyPressed
shoot: # Shoots a laser from the ship's middle blaster if a laser is not currently active
addi $t5, $s6, 0
lw $t8, ($t5)
bnez $t8, laserCurrentlyActive
lw $t0, shipAddress
add $t8, $t0, 1592
sw $t8, ($t5)
lw $a0, red
jal drawLaser
laserCurrentlyActive:
j keyPressed
checkShipCollisions:
addi $t5, $s6, 0 # Get address of array index
lw $t0, shipAddress # Get ship address and store in $t0
addi $t7, $0, 0 # store indices for obstacles
addi $t6, $0, 4
mult $t6, $s5 # Multiply number of max enemies * 4
mflo $t6
checkObstacleShip:
beq $t7, $t6, checkedAllObstacleShip
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in $t8
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noShipCollision # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
la $t1, shipHitBoxes
addi $t2, $0, 0 # To iterate through array of hitboxes
# Now check each key point of ship to see if we hit an obstacle:
# Check if top right of ship hits an obstacle
checkEachHitbox:
bge $t2, 56, noShipCollision
add $t4, $t1, $t2
lw $t4, ($t4)
add $t3, $t0, $t4 # Location of hitbox of ship
addi $t4, $t9, 0 # Location of left end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 512 # Location of left end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1024 # Location of left end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1536 # Location of left end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 2048 # Location of left end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 4 # Location of left middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 516 # Location of left middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1028 # Location of left middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1540 # Location of left middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 2052 # Location of left middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 8 # Location of middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 520 # Location of middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1032 # Location of middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1544 # Location of middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 2056 # Location of middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 12 # Location of right middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 524 # Location of right middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1036 # Location of right middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1548 # Location of right middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 2060 # Location of right middle end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 16 # Location of right end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 528 # Location of right end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1040 # Location of right end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 1552 # Location of right end of obstacle
beq $t4, $t3, obstacleHit
addi $t4, $t9, 2064 # Location of right end of obstacle
beq $t4, $t3, obstacleHit
addi $t2, $t2, 4
j checkEachHitbox
noShipCollision: # Come here if no collision occurs at all
addi $t7, $t7, 4 # Go check next obstacle in array
j checkObstacleShip
obstacleHit:
lw $t7, black # Erase the whole obstacle
sw $t7, 0($t9)
sw $t7, 4($t9)
sw $t7, 8($t9)
sw $t7, 12($t9)
sw $t7, 16($t9)
sw $t7, 512($t9)
sw $t7, 516($t9)
sw $t7, 520($t9)
sw $t7, 524($t9)
sw $t7, 528($t9)
sw $t7, 1024($t9)
sw $t7, 1028($t9)
sw $t7, 1032($t9)
sw $t7, 1036($t9)
sw $t7, 1040($t9)
sw $t7, 1536($t9)
sw $t7, 1540($t9)
sw $t7, 1544($t9)
sw $t7, 1548($t9)
sw $t7, 1552($t9)
sw $t7, 2048($t9)
sw $t7, 2052($t9)
sw $t7, 2056($t9)
sw $t7, 2060($t9)
sw $t7, 2064($t9)
sw $0, ($t8) # Reset this obstacle to 0 to delete it
# Ship takes damage
addi $t5, $s6, 4 # Get index for HP Bar element in 'otherAddresses'
lw $t8, ($t5) # Get address of current HP bar and store it in $t8
add $t8, $t8, -40 # Subtract 10 units off the HP bar (total is 60 units, so ship can take 6 hits)
lw $a0, black
# Erase portion of HP Bar
sw $t7, 40($t8)
sw $t7, 552($t8)
sw $t7, 1064($t8)
sw $t7, 36($t8)
sw $t7, 548($t8)
sw $t7, 1060($t8)
sw $t7, 32($t8)
sw $t7, 544($t8)
sw $t7, 1056($t8)
sw $t7, 28($t8)
sw $t7, 540($t8)
sw $t7, 1052($t8)
sw $t7, 24($t8)
sw $t7, 536($t8)
sw $t7, 1048($t8)
sw $t7, 20($t8)
sw $t7, 532($t8)
sw $t7, 1044($t8)
sw $t7, 16($t8)
sw $t7, 528($t8)
sw $t7, 1040($t8)
sw $t7, 12($t8)
sw $t7, 524($t8)
sw $t7, 1036($t8)
sw $t7, 8($t8)
sw $t7, 520($t8)
sw $t7, 1032($t8)
sw $t7, 4($t8)
sw $t7, 516($t8)
sw $t7, 1028($t8)
sw $t7, 0($t8)
sw $t7, 512($t8)
sw $t7, 1024($t8)
sw $t8, ($t5)
addi $t5, $s0, 29748
beq $t5, $t8, GAMEOVER # If ship takes too much damage, end the game
sw $t0, shipAddress
jr $ra # Return since laser can only hit 1 obstacle
checkedAllObstacleShip:
sw $t0, shipAddress
jr $ra
drawLaser: # Just draw/erase the laser
addi $t5, $s6, 0
lw $t8, ($t5)
beqz $t8, noLasers
sw $a0, 0($t8)
sw $a0, 4($t8)
sw $a0, 8($t8)
sw $a0, 12($t8)
sw $a0, 16($t8)
noLasers:
jr $ra
moveLaser: # Update laser position over time if laser is present
addi $t5, $s6, 0
lw $t8, ($t5)
beq $t8, 0, noLaserActive
beq $s7, 1, fireModeActive
addi $t8, $t8, 8
j storeNewLaserPosition
fireModeActive:
addi $t8, $t8, 16
storeNewLaserPosition:
sw $t8, ($t5)
noLaserActive:
jr $ra
despawnLaser:
addi $t5, $s6, 0 # Get address of array index
lw $t8, ($t5) # Get laser address
addi $t7, $t8, -496 # Check if laser address is at edge of right side of screen
addi $t6, $0, 512
div $t7, $t6
mfhi $t7
beq $t7, 0, eraseTheLaser
beq $t7, 8, eraseTheLaser
j laserStillActive
eraseTheLaser: # Erase the laser
sw $a0, 0($t8)
sw $a0, 4($t8)
sw $a0, 8($t8)
sw $a0, 12($t8)
sw $a0, 16($t8)
sw $0, ($t5)
laserStillActive:
jr $ra
checkLaserCollisions:
addi $t5, $s6, 0 # Get address of array index
lw $t0, ($t5) # Get laser address and store in $t0
addi $t7, $0, 0 # store indices for obstacles
addi $t6, $0, 4
mult $t6, $s5 # Multiply number of max enemies * 4
mflo $t6
checkAsteroidLaser:
beq $t7, $t6, checkedAllAsteroidLaser
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in $t8
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noCollision # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
addi $t4, $t0, 20
# Check if front end of laser hits an obstacle
addi $t4, $t9, 0 # Location of left end of obstacle
addi $t3, $t0, 16 # Location of right end of laser
beq $t4, $t3, laserHit
addi $t4, $t9, 512 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1024 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1536 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 2048 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 4 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 516 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1028 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1540 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 2052 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 8 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 520 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1032 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1544 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 2056 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 12 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 524 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1036 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1548 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 2060 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 16 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 528 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1040 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 1552 # Location of left end of obstacle
beq $t4, $t3, laserHit
addi $t4, $t9, 2064 # Location of left end of obstacle
beq $t4, $t3, laserHit
noCollision: # Come here if no collision occurs at all
addi $t7, $t7, 4 # Go check next obstacle in array
j checkAsteroidLaser
laserHit:
lw $t7, black # Erase the whole obstacle
sw $t7, 0($t9)
sw $t7, 4($t9)
sw $t7, 8($t9)
sw $t7, 12($t9)
sw $t7, 16($t9)
sw $t7, 512($t9)
sw $t7, 516($t9)
sw $t7, 520($t9)
sw $t7, 524($t9)
sw $t7, 528($t9)
sw $t7, 1024($t9)
sw $t7, 1028($t9)
sw $t7, 1032($t9)
sw $t7, 1036($t9)
sw $t7, 1040($t9)
sw $t7, 1536($t9)
sw $t7, 1540($t9)
sw $t7, 1544($t9)
sw $t7, 1548($t9)
sw $t7, 1552($t9)
sw $t7, 2048($t9)
sw $t7, 2052($t9)
sw $t7, 2056($t9)
sw $t7, 2060($t9)
sw $t7, 2064($t9)
sw $0, ($t8) # Reset this obstacle to 0 to delete it
sw $t7, 0($t0) # Erase the laser
sw $t7, 4($t0)
sw $t7, 8($t0)
sw $t7, 12($t0)
sw $t7, 16($t0)
sw $0, ($t5) # Reset laser to 0 to delete it
jr $ra # Return since laser can only hit 1 obstacle
checkedAllAsteroidLaser:
jr $ra
checkShipForm:
beq $s7, 0, ICE
beq $s7, 1, FIRE
beq $s7, 2, SHOCK
ICE:
add $s3, $0, 2 # set to normal ship speed
lw $v0, blue # color the ship blue
j shipCheckDone
FIRE:
add $s3, $0, 2 # set to normal ship speed
lw $v0, red # color the ship red
j shipCheckDone
SHOCK:
add $s3, $0, 4 # set to double ship speed
lw $v0, yellow # color the ship yellow
j shipCheckDone
shipCheckDone:
jr $ra
despawnObstacles:
addi $t7, $0, 0 # store indices
checkEachAsteroid:
addi $t6, $0, 4
mult $t6, $s5 # Multiply number of max enemies * 4
mflo $t6
beq $t7, $t6, checkedAllAsteroids
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noAsteroidToDespawn # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Despawn obstacle if the obstacle is at a certain x-coordinate (left side of screen)
add $t5, $0, 512
div $t9, $t5
mfhi $t5 # If address is divisible by 512, it's at the edge of the screen on the left, so despawn it
addi $s4, $s4, -1 # Remove 1 from total number of obstacles in game right now
bnez $t5, noAsteroidToDespawn # Only despawn if address is divisble by 512, as explained above
bge $t7, 32, despawnHunter # If index is 9 or greater, this is a FILLER
bge $t7, 20, despawnBerserker # If index is 5 or greater but less than 9, this is a berserker
# Else, this must be an asteroid so just carry on
# Erase the Asteroid visually
despawnAsteroid:
sw $a0, 0($t9)
sw $a0, 16($t9)
sw $a0, 516($t9)
sw $a0, 520($t9)
sw $a0, 524($t9)
sw $a0, 1028($t9)
sw $a0, 1032($t9)
sw $a0, 1036($t9)
sw $a0, 1540($t9)
sw $a0, 1544($t9)
sw $a0, 1548($t9)
sw $a0, 2048($t9)
sw $a0, 2064($t9)
addi $t9, $0, 0 # Reset this obstacle to 0 in the obstacle array (and we don't need to mess with speed array since the arrays are parallel anyway)
sw $t9, ($t8) # Store 0 into corresponding array element (i.e. reset the array at this index)
j noAsteroidToDespawn
# Erase the Berserker visually
despawnBerserker:
sw $a0, 0($t9)
sw $a0, 4($t9)
sw $a0, 16($t9)
sw $a0, 516($t9)
sw $a0, 520($t9)
sw $a0, 524($t9)
sw $a0, 1024($t9)
sw $a0, 1028($t9)
sw $a0, 1032($t9)
sw $a0, 1036($t9)
sw $a0, 1040($t9)
sw $a0, 1540($t9)
sw $a0, 1544($t9)
sw $a0, 1548($t9)
sw $a0, 2048($t9)
sw $a0, 2052($t9)
sw $a0, 2064($t9)
addi $t9, $0, 0 # Reset this obstacle to 0 in the obstacle array (and we don't need to mess with speed array since the arrays are parallel anyway)
sw $t9, ($t8) # Store 0 into corresponding array element (i.e. reset the array at this index)
j noAsteroidToDespawn
# Erase the Hunter visually
despawnHunter:
sw $a0, 0($t9)
sw $a0, 4($t9)
sw $a0, 8($t9)
sw $a0, 12($t9)
sw $a0, 16($t9)
sw $a0, 512($t9)
sw $a0, 528($t9)
sw $a0, 1032($t9)
sw $a0, 1040($t9)
sw $a0, 1536($t9)
sw $a0, 1552($t9)
sw $a0, 2048($t9)
sw $a0, 2052($t9)
sw $a0, 2056($t9)
sw $a0, 2060($t9)
sw $a0, 2064($t9)
addi $t9, $0, 0 # Reset this obstacle to 0 in the obstacle array (and we don't need to mess with speed array since the arrays are parallel anyway)
sw $t9, ($t8) # Store 0 into corresponding array element (i.e. reset the array at this index)
j noAsteroidToDespawn
noAsteroidToDespawn:
addi $t7, $t7, 4 # Go to next element in array
j checkEachAsteroid
checkedAllAsteroids:
jr $ra
drawObstacles: # set $t to black if erasing, to a color if coloring
addi $t7, $0, 0 # store indices
drawEachAsteroid:
addi $t6, $0, 4
mult $t6, $s5 # Multiply number of max enemies * 4
mflo $t6
beq $t7, $t6, finishedDrawingAsteroids
beq $t7, 20, finishedDrawingAsteroids # A game can have at most 5 asteroids.
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noAsteroidToDraw # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Draw asteroid sprite
sw $a0, 0($t9)
sw $a0, 16($t9)
sw $a0, 516($t9)
sw $a0, 520($t9)
sw $a0, 524($t9)
sw $a0, 1028($t9)
sw $a0, 1032($t9)
sw $a0, 1036($t9)
sw $a0, 1540($t9)
sw $a0, 1544($t9)
sw $a0, 1548($t9)
sw $a0, 2048($t9)
sw $a0, 2064($t9)
noAsteroidToDraw:
addi $t7, $t7, 4 # Go to next element in array
j drawEachAsteroid
finishedDrawingAsteroids:
# Start drawing berserkers
drawEachBerserker:
beq $t7, $t6, finishedDrawingBerserkers
beq $t7, 32, finishedDrawingBerserkers # A game can have at most 3 berserkers.
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noBerserkerToDraw # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Draw berserker sprite
sw $a1, 0($t9)
sw $a1, 4($t9)
sw $a1, 16($t9)
sw $a1, 516($t9)
sw $a1, 520($t9)
sw $a1, 524($t9)
sw $a1, 1024($t9)
sw $a1, 1028($t9)
sw $a1, 1032($t9)
sw $a1, 1036($t9)
sw $a1, 1040($t9)
sw $a1, 1540($t9)
sw $a1, 1544($t9)
sw $a1, 1548($t9)
sw $a1, 2048($t9)
sw $a1, 2052($t9)
sw $a1, 2064($t9)
noBerserkerToDraw:
addi $t7, $t7, 4 # Go to next element in array
j drawEachBerserker
finishedDrawingBerserkers:
drawEachHunter:
beq $t7, $t6, finishedDrawingHunters
beq $t7, 40, finishedDrawingHunters # A game can have at most 2 hunters
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
ble $t9, $0, noHunterToDraw # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Draw Hunter sprite
sw $a1, 0($t9)
sw $a1, 4($t9)
sw $a1, 8($t9)
sw $a1, 12($t9)
sw $a1, 16($t9)
sw $a1, 512($t9)
sw $a1, 528($t9)
sw $a1, 1032($t9)
sw $a1, 1040($t9)
sw $a1, 1536($t9)
sw $a1, 1552($t9)
sw $a1, 2048($t9)
sw $a1, 2052($t9)
sw $a1, 2056($t9)
sw $a1, 2060($t9)
sw $a1, 2064($t9)
noHunterToDraw:
addi $t7, $t7, 4 # Go to next element in array
j drawEachHunter
finishedDrawingHunters:
jr $ra
moveObstacles:
addi $t7, $0, 0 # store indices
moveEachAsteroid:
addi $t6, $0, 4
mult $t6, $s5 # Multiply number of max enemies * 4
mflo $t6
beq $t7, $t6, movedAllAsteroids
beq $t7, 20, movedAllAsteroids # Can have at most 5 asteroids at a time
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
add $t5, $s2, $t7 # Put address of element of 'speeds' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
lw $t6, ($t5) # Load in the corresponding speed of obstacle into $t6
ble $t9, $0, noAsteroid # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Make obstacles move 1 time left
addi $t5, $0, -4
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array
mflo $t5
add $t9, $t9, $t5 # Move address left
sw $t9, ($t8) # Store the corresponding new address into $t8
noAsteroid:
addi $t7, $t7, 4 # Go to next element in array
j moveEachAsteroid
movedAllAsteroids:
moveEachBerserker:
beq $t7, $t6, movedAllBerserkers
beq $t7, 32, movedAllBerserkers # Can have at most 3 berserkers in a game
add $t8, $s1, $t7 # Put address of element of 'obstacles' at index $t7 / 4 in here
add $t5, $s2, $t7 # Put address of element of 'speeds' at index $t7 / 4 in here
lw $t9, ($t8) # Load in the corresponding element of 'obstacles' into $t9
lw $t6, ($t5) # Load in the corresponding speed of obstacle into $t6
ble $t9, $0, noBerserker # If element is less than or equal to 0, this is an empty slot and we don't need to do anything to it
# Make obstacles randomly move 1 time left, up, or down based on their speed in the speed array
li $v0, 42
li $a0, 0
li $a1, 3
syscall
beq $a0, 0, berserkLeft
beq $a0, 1, berserkUp
beq $a0, 2, berserkDown
berserkLeft:
addi $t5, $0, -4
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array: 4 * speed
mflo $t5
add $t9, $t9, $t5 # Move address left
sw $t9, ($t8) # Store the corresponding new address into $t8
j noBerserker
berserkUp:
addi $t5, $0, -512
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array: 4 * speed
mflo $t5
add $t5, $t9, $t5
ble $t5, $s0, berserkLeft # If going up makes the berserker go out of bounds, just go left instead
addi $t5, $0, -512
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array: 4 * speed
mflo $t5
add $t9, $t9, $t5 # Move address up
sw $t9, ($t8) # Store the corresponding new address into $t8
j noBerserker
berserkDown:
addi $t5, $0, 512
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array: 4 * speed
mflo $t5
add $t4, $t9, $t5
add $t5, $s0, 25084
bge $t4, $t5, berserkLeft # If going down makes the berserker go out of bounds, just go left instead
addi $t5, $0, 512
mult $t5, $t6 # This is how many units the obstacle will move based on their speed from speed array: 4 * speed
mflo $t5
add $t9, $t9, $t5 # Move address down
sw $t9, ($t8) # Store the corresponding new address into $t8
j noBerserker
noBerserker:
addi $t7, $t7, 4 # Go to next element in array