บทความนี้แนะนำการเขียนเกมเตตริส (Tetris) แบบง่าย โดยแสดงผลในตารางขนาด กว้าง 10 ช่อง และสูง 16 ช่อง ตามภาพที่ 1 โดยใช้บอร์ดไมโครคอนโทรลเลอร์ esp32 ที่ต่อกับจอแสดงผลแบบ ST7735 และสวิตช์สำหรับควบคุมอีก 8 ตัว ที่สำคัญคือ เขียนด้วยภาษาไพธอนผ่าน MicroPython ที่คอมไพล์ให้ใช้ชุดไลบรารี st7735_mpy ซึ่งในบทความนี้กล่าวถึงการจัดเก็บวัตถุทั้ง 7 แบบที่เป็นสิ่งของหรือวัตถุที่ตกลงมาให้รองรับการแสดงผลและการหมุนวัตถุ กับการเลื่อนวัตถุไปทางซ้ายและขวา ส่วนการควบคุมและตรรกะของเกม Tetris จะกล่าวในบทความถัดไป
โครงสร้างข้อมูล
เกม Tetris มีข้อมูลหลักที่ต้องจัดเก็บคือ วัตถุที่ตกลงมาทั้ง 7 แบบ ดังภาพที่ 1 ถึง 8 ซึ่งจะพบว่า ถูกเก็บในลักษะของตาางข้อมูลขนาด 4×4 โดยถ้าตำแหน่งใดเป็นส่วนของวัตถุจะเก็บค่า 1 แต่ถ้าตำแหน่งใดไม่ใช่ตัววัตถุจะเก็บเป็นค่า 0 โดยโครงสร้างข้อมูลของวัตถุแต่ละแบบเป็นดังนี้
วัตถุแบบที่ 1
วัตถุแบบแรกเป็นแท่งยาว 4 ช่อง สูง 1 ช่องดังภาพที่ 2 และเมื่อกดหมุนจะกลายเป็นแท่งสูง 4 ช่อง และกว้าง 1 ช่อง
การจัดเก็บข้อมูลของวัตถุที่ 1 เพื่อให้รองรับการหมุนได้ 2 แบบ เป็นดังนี้
[ # แบบ1
[[1,1,1,1], # rotate=0
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,0,0,0],
[1,0,0,0],
[1,0,0,0]]
]
วัตถุแบบที่ 2
วัตถุแบบที่ 2 เป็นตามภาพที่ 3 สามารถหมุนได้ 4 แบบ และให้ผลในเรื่องของขนาดของวัตถุเปลี่ยนแปลงเป็น คือ เป็น 2×3, 3×2, 2×3 และ 3×2 ดังภาพ
การจัดเก็บข้อมูลของวัตถุที่ 2 เพื่อให้รองรับการหมุนได้ 4 แบบ เป็นดังนี้
[ # แบบ 2
[[1,1,1,0], # rotate=0
[1,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=1
[0,1,0,0],
[0,1,0,0],
[0,0,0,0]],
[[0,0,1,0], # rotate=2
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=3
[1,0,0,0],
[1,0,0,0],
[0,0,0,0]]
]
วัตถุแบบที่ 3
วัตถุประเภทนี้คล้ายกับแบบที่ 2 แต่การวางตำแหน่งตรงกันข้ามกันดังภาพที่ 4
การจัดเก็บข้อมูลของวัตถุที่ 3 เพื่อให้รองรับการหมุนได้ 4 แบบ เป็นดังนี้
[ # แบบ 3
[[1,0,0,0], # rotate=0
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=1
[1,0,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,1,0], # rotate=2
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=3
[0,1,0,0],
[1,1,0,0],
[0,0,0,0]]
]
วัตถุแบบที่ 4
วัตถุแบบที่ 4 เป็นแท่งยาว 3 ช่องที่มีส่วนที่ยื่นออกมาตรงกลางดังภาพที่ 5 ทำให้ขนาดของวัตถุเมื่อมีการหมุนในมุมต่าง ๆ เป็น 2×3, 3×2, 2×3 และ 3×2
การจัดเก็บข้อมูลของวัตถุที่ 4 เพื่อให้รองรับการหมุนได้ 4 แบบ เป็นดังนี้
[ # แบบ 4
[[0,1,0,0], # rotate=0
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,1,0], # rotate=2
[0,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=3
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]],
]
วัตถุแบบที่ 5
วัตถุแบบที่ 5 มีขนาด 2×3 และเมื่อหมุนจะกลายเป็น 3×2 ดังภาพที่ 6
การจัดเก็บข้อมูลของวัตถุที่ 5 เพื่อให้รองรับการหมุนได้ 2 แบบ เป็นดังนี้
[ # แบบ 5
[[0,1,1,0], # rotate=0
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]]
]
วัตถุแบบที่ 6
วัตถุแบบที่ 6 เป็นวัตถุที่อยู่ตรงกันข้ามกับวัตถุแบบที่ 5 ดังภาพที่ 7
การจัดเก็บข้อมูลของวัตถุที่ 6 เพื่อให้รองรับการหมุนได้ 2 แบบ เป็นดังนี้
[ # แบบ 6
[[1,1,0,0], # rotate=0
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=1
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]]
]
วัตถุแบบที่ 7
วัตถุประเภทนี้มีขนาด 2×2 เหมือนกล่องสี่เหลี่ยมจึงทำให้หมุนอย่างไรก็ได้รูปทรงเดิม จึงไม่จำเป็นต้องหมุนวัตถุดังภาพที่ 8
การจัดเก็บข้อมูลของวัตถุที่ 7 เป็นดังนี้
[ # แบบ 7
[[1,1,0,0], # rotate=0
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]]
]
การเคลื่อนที่
อุปกรณ์นำเข้าประกอบด้วยสวิตช์ 8 ตัวที่ต่อแบบ Pull-up โดยกำหนดชื่อเรียก ดังภาพที่ 9 และ 10
การกำหนดค่าสำหรับสวิตช์ทั้ง 8 เป็นดังนี้
keL = Pin(39, Pin.IN, Pin.PULL_UP)
keU = Pin(34, Pin.IN, Pin.PULL_UP)
keD = Pin(35, Pin.IN, Pin.PULL_UP)
keR = Pin(32, Pin.IN, Pin.PULL_UP)
swM1 = Pin(33, Pin.IN, Pin.PULL_UP)
swM2 = Pin(25, Pin.IN, Pin.PULL_UP)
swA = Pin(26, Pin.IN, Pin.PULL_UP)
swB = Pin(27, Pin.IN, Pin.PULL_UP)
การสุ่มวัตถุ
การสุ่มวัตถุใช้การสุ่มจากคลาส random โดยกำหนดช่วงค่าเป็น 0 ถึง 6 แทนวัตถุประเภทที่ 1 ถึง 7 ซึ่งการทำงานของการสุ่มเมื่อกด swM2 เป็นดังนี้
actorNo = random.randint(0,len(actors)-1)
การเลื่อนไปทางซ้าย
เนื่องจากวัตถุทุกชิ้นมีตำแหน่งเริ่มต้นที่มุมซ้ายบน ทำให้สามารถเลื่อนไปทางซ้ายด้วยการลดค่า posX ยกเว้นกรณีที่อยู่ขอบจออยู่แล้วจะไม่ลดค่าตำแหน่งดังโค้ดต่อไปนี้
if posX > 0:
table()
posX -= 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 1
หลักการทำงานของการเลื่อนวัตถุไปทางขวาจะอาศัยค่า posX และ actorRotate เป็นตัวแปรสำหรับพิจารณาการเลื่อน ดังนี้
- ถ้า actorRotate เป็น 0 หมายถึงวัตถุมีความยาว 4 ช่อง ดังนั้น ถ้าพื้นที่ทางขวาไม่มากพอจะไม่ขยับ แต่ถ้าพอจะทำการขยับไปทางขวาด้วยการเพิ่มค่า posX
- ถ้า actorRotate เป็น 1 ทำให้วัตถุมีความกว้างเป็น 1 ดังนั้น ถ้าวัตถุยังไม่ชิดช่องด้านขวาจะเพิ่มค่า posX
โค้ดของการทำงานเป็นดังนี้
if (actorRotate == 0):
maxX = maxCol-4
else:
maxX = maxCol-1
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 2
หลักการทำงานของการเลื่อนวัตถุไปทางขวาของวัตถุประเภทที่ 2 นั้นอาศัยค่า posX และ actorRotate เป็นตัวแปรสำหรับพิจารณาการเลื่อน ดังนี้
- ถ้า actorRotate เป็น 0 หมายถึงวัตถุมีความยาว 3 ช่อง ดังนั้น ถ้าพื้นที่ทางขวาไม่มากพอจะไม่ขยับ แต่ถ้าพอจะทำการขยับไปทางขวาด้วยการเพิ่มค่า posX
- ถ้า actorRotate เป็น 1 ทำให้วัตถุมีความกว้างเป็น 2 ดังนั้น ถ้าวัตถุยังไม่ชิดช่องด้านขวาจะเพิ่มค่า posX
- ถ้า actorRotate เป็น 2 ทำให้วัตถุมีความกว้าง 2 ช่อง ทำให้สามารถขยับไปทางขวาได้ถ้ายังมีพื้นที่ทางขวาเหลืออยู่
- ถ้า actorRotate เป็น 3 เป็นเหมือนกรณีที่ 2
โค้ดของการทำงานเป็นดังนี้
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 3
หลักการทำงานของการเลื่อนวัตถุไปทางขวาของวัตถุประเภทที่ 3 จะเหมือนกับแบบที่ 2 โดยโค้ดของการทำงานเป็นดังนี้
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 4
การขยับวัตถุประเภทที่ 4 ไปทางขวาจะมีหลักการเช่นเดียวกับวัตถุประเภทที่ 2 และ 3 ดังนี้
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 5
การเคลื่อนที่วัตถุประเภทที่ 5 ไปทางขวาจะพิจารณาว่าตำแหน่งว่างทางขวามีเหลือเพียงพอหรือไม่ คือ ถ้าอยู่ในสถานะการหมุนแบบที่ 0 จะต้องมีพื้นที่ 3 หน่วย ถ้าเป็นแบบที่ 1 จะต้องมีพื้นที่ 2 หน่วยหรือ 2 ช่อง ดังโค้ดต่อไปนี้
if (actorRotate == 0):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 6
การเคลื่อนที่วัตถุประเภทที่ 6 มีหลัการเหมือนกับวัตถุประเภทที่ 6 ดังโค้ดต่อไปนี้
if (actorRotate == 0):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
การเลื่อนไปทางขวาของวัตถุประเภท 7
การย้ายวัตถุประเภทที่ 7 ไปทางขวาจะต้องมีพื้นที่ทางขวาอย่างน้อย 2 ช่อง ดังโค้ดต่อไปนี้
if posX < (maxCol-2):
table()
posX += 1
draw()
การหมุนวัตถุประเภทที่ 1
การหมุนวัตถุประเภทที่ 1 จะหมุนจาก 1 เป็น 0 ได้จะต้องมีพื้นที่ทางขวาเหลืออย่างน้อย 4 ช่อง ดังการตรวจสอบด้วยโค้ดต่อไปนี้
actorRotate += 1
if actorRotate > 1:
if (posX > (maxCol-4)): # ถ้าตำแหน่งเกินขอบให้หมุนกลับไปตำแหน่งที่เหมาะสม
actorRotate = 1
else:
actorRotate = 0
การหมุนวัตถุประเภทที่ 2
สำหรับวัตถุประเภทที่ 2 มีหลักการตรวจสอบการหมุนดังนี้
- เปลี่ยนจากการหมุนแบบ 0 ไป 1 จะต้องมีพื้นที่ทางขวาเหลือ 2 หน่วย
- เปลี่ยนจากการหมุนแบบ 1 ไป 2 จะต้องมีพื้นที่ทางขวเหลือ 3 หน่วย
- เปลี่ยนจากการหมุนแบบ 2 ไป 3 จะต้องมีพื้นที่ทางขวาเหลืออยู่อย่างน้อย 2 หน่วย
- เปลี่ยนจากการหมุนแบบ 3 ไป 0 จะต้องมีพื้นที่ทางขวาเหลืออยู่อย่างน้อย 3 หน่วย
- กรณีอื่น ๆ จะไม่สามารถหมุนได้
โค้ดของการตรวจสอบการหมุนเป็นดังนี้
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
การหมุนวัตถุประเภทที่ 3
มีหลักการเช่นเดียวกับวัตถุประเภทที่ 2 ดังโค้ดต่อไปนี้
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
การหมุนวัตถุประเภทที่ 4
สำหรับการหมุนของวัตถุประเภทที่ 4 นั้นมีหลักการเหมือนกับการหมุนวัตถุประเภทที่ 2 และ 3 ดังโค้ดของการตรวจสอบการหมุนต่อไปนี้
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
การหมุนวัตถุประเภทที่ 5
การหมุนวัตถุประเภทที่ 5 มีเงื่อนไขการทำงานดังนี้
- หมุนจากสถานะ 0 เป็น 1 จะต้องมีพื้นที่ทางขวาเหลือ 2 ช่อง
- เปลี่ยนจากสถานะ 1 เป็น 0 จะต้องมีพื้นที่ทางขวาเหลืออยู่อย่างน้อย 3 ช่อง
- กรณีอื่น ๆ จะไม่สามารถหมุนได้
สำหรับโค้ดตรวจสอบการหมุนวัตถุประเภทที่ 5 คือ
if actorRotate == 0:
actorRotate = 1
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 1
การหมุนวัตถุประเภทที่ 6
การหมุนวัตถุประเภทที่ 6 มีหลักการเหมือนกับการหมุนวัตถุประเภทที่ 5 ดังโค้ดต่อไปนี้
if actorRotate == 0:
actorRotate = 1
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 1
การหมุนวัตถุประเภทที่ 7
เนื่องจากวัตถุประเภทที่ 7 เป็นสี่เหลี่ยมจัตุรัสขนาด 2×2 ทำให้การหมุนมีค่าเท่าเดิมจึงข้ามการตรวจสอบการหมุนของวัตถุประเภทนี้
ตัวอย่างโปรแกรม
จากโครงสร้างข้อมูลและการกำหนดเกี่ยวกับการรับค่าพร้อมทั้งเงื่อนไขของการรับค่า/แสดงผล เขียนโค้ดได้ดังนี้ โดยกำหนดให้
- swM1 สำหรับออกจากโปรแกรม
- swM2 สำหรับสุ่มวัตถุใหม่
- swA สำหรับหมุนวัตถุ
- keL สำหรับเลื่อนตำแหน่งวัตถุไปทางซ้าย
- keR สำหรับเลื่อนตำแหน่งวัตถุไปทางขวา
#################################################################
# tetris
# JarutEx 2021-11-06
#################################################################
import gc
import os
import sys
import time
import machine as mc
from machine import Pin,SPI
import math
import st7735 as tft
import vga1_16x16 as font
import random
#################################################################
###### setting ##################################################
#################################################################
gc.enable()
gc.collect()
mc.freq(240000000)
spi = SPI(2, baudrate=26000000,
sck=Pin(14), mosi=Pin(12),
polarity=0, phase=0)
#### Key
keL = Pin(39, Pin.IN, Pin.PULL_UP)
keU = Pin(34, Pin.IN, Pin.PULL_UP)
keD = Pin(35, Pin.IN, Pin.PULL_UP)
keR = Pin(32, Pin.IN, Pin.PULL_UP)
swM1 = Pin(33, Pin.IN, Pin.PULL_UP)
swM2 = Pin(25, Pin.IN, Pin.PULL_UP)
swA = Pin(26, Pin.IN, Pin.PULL_UP)
swB = Pin(27, Pin.IN, Pin.PULL_UP)
spk = Pin(19,Pin.OUT)
spk.on()
time.sleep(0.1)
spk.off()
# dc, rst, cs
scr = tft.ST7735(spi, 128, 160, dc=Pin(15, Pin.OUT), reset=Pin(13,Pin.OUT), cs=Pin(2, Pin.OUT), rotation=3)
scr.initr()
actors = [
[ # แบบ1
[[1,1,1,1], # rotate=0
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,0,0,0],
[1,0,0,0],
[1,0,0,0]]
],
[ # แบบ 2
[[1,1,1,0], # rotate=0
[1,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=1
[0,1,0,0],
[0,1,0,0],
[0,0,0,0]],
[[0,0,1,0], # rotate=2
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=3
[1,0,0,0],
[1,0,0,0],
[0,0,0,0]]
],
[ # แบบ 3
[[1,0,0,0], # rotate=0
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0], # rotate=1
[1,0,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,1,0], # rotate=2
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=3
[0,1,0,0],
[1,1,0,0],
[0,0,0,0]]
],
[ # แบบ 4
[[0,1,0,0], # rotate=0
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,1,0], # rotate=2
[0,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=3
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]],
],
[ # แบบ 5
[[0,1,1,0], # rotate=0
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0], # rotate=1
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]]
],
[ # แบบ 6
[[1,1,0,0], # rotate=0
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0], # rotate=1
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]]
],
[ # แบบ 7
[[1,1,0,0], # rotate=0
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]]
]
]
actorColors = [
tft.color565(232,232,64),
tft.color565(232,64,64),
tft.color565(232,64,232),
tft.color565(64,64,232),
tft.color565(64,232,64),
tft.color565(64,232,232),
tft.color565(232,232,232)
]
actorRotate = 0
actorNo = random.randint(0,len(actors)-1)
maxCol = 10
maxRow = 16
posX = 0
posY = 0
#################################################################
###### sub modules ##############################################
#################################################################
def splash():
scr.fill(tft.color565(0x00,0x00,0x00))
scr.text(font,"JarutEx", 20, 20, tft.YELLOW, tft.BLACK)
scr.text(font,"JarutEx", 21, 20, tft.YELLOW, tft.BLACK)
scr.text(font,"(C)2021", 40,48, tft.CYAN, tft.BLACK)
time.sleep_ms(2000)
scr.fill(tft.BLACK)
def table():
blankColor = tft.color565(48, 48, 48)
for i in range(maxRow):
for j in range(maxCol):
x = j * 8 + 1
y = i * 8 + 1
w = 6
h = 6
scr.fill_rect(x,y,w,h, blankColor)
def draw():
actor = actors[actorNo][actorRotate]
for i in range(4):
for j in range(4):
if actor[i][j]:
x = (posX+j) * 8 + 1
y = (posY+i) * 8 + 1
w = 6
h = 6
scr.fill_rect(x,y,w,h,actorColors[actorNo])
#################################################################
###### main program #############################################
#################################################################
splash()
table()
draw()
while swM1.value():
if swM2.value() == 0:
table()
actorNo = random.randint(0,len(actors)-1)
posX = 0
posY = 0
actorRotate = 0
draw()
if swA.value() == 0: # rotate
table()
if (actorNo == 0):
actorRotate += 1
if actorRotate > 1:
if (posX > (maxCol-4)): # ถ้้าตำแหน่งเกินขอบให้หมุนกลับไปตำแหน่งที่เหมาะสม
actorRotate = 1
else:
actorRotate = 0
elif (actorNo == 1):
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
elif (actorNo == 2):
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
elif (actorNo == 3):
if actorRotate == 0:
actorRotate = 1
elif actorRotate == 1:
if (posX < (maxCol - 2)):
actorRotate = 2
else:
actorRotate = 1
elif actorRotate == 2:
actorRotate = 3
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 3
elif (actorNo == 4):
if actorRotate == 0:
actorRotate = 1
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 1
elif (actorNo == 5):
if actorRotate == 0:
actorRotate = 1
else:
if (posX < (maxCol - 2)):
actorRotate = 0
else:
actorRotate = 1
draw()
if keL.value() == 0:
if posX > 0:
table()
posX -= 1
draw()
if keR.value() == 0:
if (actorNo == 0):
if (actorRotate == 0):
maxX = maxCol-4
else:
maxX = maxCol-1
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 1):
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 2):
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 3):
if (actorRotate == 0):
maxX = maxCol-3
elif (actorRotate == 1):
maxX = maxCol-2
elif (actorRotate == 2):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 4):
if (actorRotate == 0):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 5):
if (actorRotate == 0):
maxX = maxCol-3
else:
maxX = maxCol-2
if posX < maxX:
table()
posX += 1
draw()
elif (actorNo == 6):
if posX < (maxCol-2):
table()
posX += 1
draw()
time.sleep_ms(100)
scr.fill(0)
spi.deinit()
สรุป
จากบทความจะเห็นว่า การออกแบบวิธีการเก็บข้อมูลมีผลสำคัญต่อการเขียนโปรแกรมพอสมควร เช่น ถ้าไม่เก็บข้อมูลการถูกหมุนลงในตัวแปร ผู้เขียนโปรแกรมจะต้องเขียนโปรแกรมคำนวณตำแหน่งหลังจากทำการหมุนวัตถุนั้นไป 90, 180 และ 270 องศา หลังจากนั้นทำการแสดงผล ซึ่งการเขียนโปรแกรมกับเครื่องคอมพิวเตอร์คงไม่ส่งผลต่อการทำงานเท่าไร แต่เมื่อใช้กับไมโครคอนโทรลเลอร์ที่มีการทำงานที่ช้ากว่ายิ่มทำให้การคำนวณนั้นกินเวลาและการแสดงผลจะล่าช้าตามไปด้วย แต่อย่างไรก็ดี ด้วยความตั้งใจจะเขียนโค้ดให้มีการปรับแต่งน้อยที่สุด ทำให้การออกแบบโครงสร้างข้อมูลนั้นสิ้นเปลืองพอสมควร เพื่อแลกกับความง่ายต่อการอธิบายและศึกษา
สุดท้ายนี้หวังว่าตัวอย่างของบทความนี้คงมีประโยชน์และสร้างแนวคิดให้กับผู้ที่สนใจพัฒนาเกมแบบทำเองง่าย ๆ และสามารถทำได้ด้วยตนเอง ขอให้สนุกกับการเขียนโปรแกรมครับ
(C) 2020-2022, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-11-07, 2022-01-10