Hobby Basic, ένας μικρός διερμηνευτής για την κονσόλα των Windows

Φτιάχνοντας ένα KLOTSKI στην Hobby BASIC - Αναλυτικό Tutorial​


Περιεχόμενα
  1. Εισαγωγή
  2. Ρύθμιση Παραθύρου και Χρωμάτων
  3. Τα Macros του Ποντικιού
  4. Η Δομή των Blocks
  5. Το Σύστημα Αποθήκευσης Προόδου
  6. Το Κύριο Loop του Παιχνιδιού
  7. Το Σύστημα Μετακίνησης
  8. Collision Detection
  9. Τα Επίπεδα (Levels)
  10. Ολόκληρος ο Κώδικας


1. Εισαγωγή​

Το Klotski είναι ένα κλασικό παιχνίδι παζλ όπου στόχος είναι να μετακινήσουμε blocks ώστε να ελευθερώσουμε το λευκό block προς την έξοδο στην κορυφή. Η υλοποίησή μας στην Hobby BASIC περιλαμβάνει:
  • 13 προοδευτικά επίπεδα
  • Μετακίνηση blocks με το ποντίκι (σύρσιμο)
  • Περιορισμό κίνησης (μόνο οριζόντια ή μόνο κάθετα)
  • Έλεγχο συγκρούσεων σε πραγματικό χρόνο
  • Αυτόματη αποθήκευση προόδου

To KLOTSKI στην κονσόλα των Windows 11.

1772189437219.png



2. Ρύθμιση Παραθύρου και Χρωμάτων​

Έλεγχος Έκδοσης Windows​

Κώδικας:
if VAL(PATH(6)) < 6
    alert 0x10, PATH(3), "Klotski requires Windows 7 or later" : end
endif
Το PATH(6) επιστρέφει την έκδοση των Windows. Αν είναι μικρότερη από 6 (Windows Vista ή παλαιότερα), εμφανίζεται μήνυμα λάθους.

Ρύθμιση Οθόνης​

Κώδικας:
title "Klotski in Hobby BASIC"
view 7            ! 8x8 pixel font
screen 41, 42, 0  ! Παράθυρο 41x42
cursor 0          ! Απόκρυψη cursor
  • view 7: Χρήση γραμματοσειράς 8x8 για περισσότερη λεπτομέρεια
  • screen 41, 42: Δημιουργία παραθύρου 41x42 χαρακτήρων
  • cursor 0: Απόκρυψη του δρομέα

Παλέτα Χρωμάτων​

Κώδικας:
dim palette[16] = \
0x000000, 0x532B1C, 0x54247F, 0x518700, \
0x3652AB, 0x511BED, 0xC6C3C3, 0xFFFFFF, \
0x4F5860, 0x1BA2FA, 0x2FECF7, 0x4DBB5D, \
0xDCA651, 0x9C7683, 0xA676F1, 0xABCCFC

times 16 \
    rgb V3, palette[V3]
Ορίζουμε 16 χρώματα σε μορφή RGB (0xBBGGRR). Η εντολή times τα φορτώνει one by one. O V3 είναι ο εσωτερικός μετρητής της times.

Σταθερές Παιχνιδιού​

Κώδικας:
BOARD_TOP = 5
BOARD_LEFT = 5
BOARD_WIDTH = 31
BOARD_HEIGHT = 31
EXIT_ZONE_TOP = 7
COLOR_TARGET_BLOCK = 7  ! Λευκό χρώμα
Το ταμπλό είναι 31*31 κελιά, ξεκινώντας από τη θέση (5,5). Η έξοδος βρίσκεται στις σειρές 0-7.



3. Τα Macros του Ποντικιού​

Κώδικας:
click_mouse() fix ((mouse_click = 1 or mouse_click = 4) and (mouse_x > 5 and mouse_x < 35 and mouse_y > 5 and mouse_y < 35))
get_mouse() fix mouse : mouse_x = V0 : mouse_y = V1 : mouse_click = V2
Αυτά τα macros (FIX) είναι τα έξυπνα κομμάτια του κώδικα:
  • get_mouse(): Καλεί την εντολή mouse και αποθηκεύει:
    • V0 → mouse_x (συντεταγμένη Χ)
    • V1 → mouse_y (συντεταγμένη Υ)
    • V2 → mouse_click (κατάσταση κουμπιού: -1 = πατημένο, 1 = μόλις πατήθηκε, 0 = ελεύθερο)
  • click_mouse(): Ελέγχει αν:
    1. Πατήθηκε το αριστερό κουμπί (1) ή έγινε double-click (4)
    2. Το ποντίκι είναι μέσα στα όρια του ταμπλό (5-35)


4. Η Δομή των Blocks​

Κάθε block ορίζεται ως μια σύνθετη μεταβλητή (type) με πεδία:
Κώδικας:
type b11 (x=6, y=6, w=4, h=14, c=1, d=0)

Πεδίο Σημασία Τιμές
x, yΘέση πάνω αριστερά 6-35
w, hΠλάτος, Ύψος4-14 pixels
cΧρώμα (color index)0-15
dDirection (κατεύθυνση κίνησης)
0 = κάθετα, 1 = οριζόντια​

Στο Klotski, κάθε block είτε κινείται μόνο πάνω-κάτω (d=0) είτε μόνο αριστερά-δεξιά (d=1).



5. Το Σύστημα Αποθήκευσης Προόδου​

Κώδικας:
path_status$ = PATH("DATA\SAVES\KLOTSKI.TXT")
if FILE(path_status$, FILE_OR_FOLDER_EXISTS) = 0 then save path_status$, GEN(14, "0")
load path_status$, level_solved$

if LEN(level_solved$) <> 14
    save path_status$, GEN(14, "0")
    load path_status$, level_solved$
endif
  • PATH(): Δημιουργεί πλήρη διαδρομή αρχείου (π.χ. "C:\HB\DATA\SAVES\KLOTSKI.TXT")
  • FILE(...,FILE_OR_FOLDER_EXISTS ): Ελέγχει αν υπάρχει το αρχείο
  • GEN(14, "0"): Δημιουργεί string 14 χαρακτήρων "00000000000000"
  • level_solved$: Κάθε χαρακτήρας είναι '1' αν το επίπεδο λύθηκε, '0' αν όχι
Το παιχνίδι ελέγχει αν το αρχείο έχει σωστό μήκος (14 χαρακτήρες για 13 επίπεδα γιατί ξεκινάμε από level 1) και το διορθώνει αν χρειάζεται.



6. Το Κύριο Loop του Παιχνιδιού​

Το κύριο loop (main#) εκτελείται συνεχώς και κάνει τρία πράγματα:
Κώδικας:
if KEY(VK_ESC)
    view 11 : color 0, 7 : cls : end
elseif KEY(VK_SPACE)
    do : until not KEY(VK_SPACE)  ! Περιμένει να αφεθεί το πλήκτρο
    goto level//level             ! Επαναφορά επιπέδου
  • ESC: Έξοδος
  • SPACE: Επαναφορά επιπέδου
  • 1/2: Προηγούμενο/Επόμενο επίπεδο

6.2 Έλεγχος Ποντικιού​

Κώδικας:
get_mouse()
if click_mouse()
    cinfo mouse_x, mouse_y
    clicked_color = V1
    ! Βρες ποιο block πατήθηκε (από το χρώμα)
Η cinfo επιστρέφει πληροφορίες για το κελί:
  • V0: Χρώμα φόντου (background)
  • V1: Χρώμα χαρακτήρα (foreground) - ΑΥΤΟ χρησιμοποιούμε!
Τα blocks σχεδιάζονται με paint που βάφει background και foreground με το ίδιο χρώμα.

6.3 Wait για Ομαλή Λειτουργία​

Κώδικας:
wait 1
goto main
Το wait 1 δίνει χρόνο στο σύστημα και περιορίζει την χρήση της CPU.



7. Το Σύστημα Μετακίνησης​

Όταν πατηθεί ένα block, μπαίνουμε σε drag loop:
Κώδικας:
do
    get_mouse()
    old_x = selected_x : old_y = selected_y

    ! Κίνηση ανάλογα με την κατεύθυνση
    if selected_dir = 0  ! Κάθετη κίνηση
        new_y = mouse_y - drag_offset_y
        if new_y >= 6 and (new_y + selected_h) <= 35
            selected_y = new_y
        endif
    else                 ! Οριζόντια κίνηση
        new_x = mouse_x - drag_offset_x
        if new_x >= 6 and (new_x + selected_w) <= 35
            selected_x = new_x
        endif
    endif

    if selected_x <> old_x or selected_y <> old_y
        if check_collision()
            selected_x = old_x
            selected_y = old_y
        else
            b//level//selected_index:[].y = selected_y
            b//level//selected_index:[].x = selected_x
            move old_x, old_y, selected_w, selected_h, selected_x, selected_y
        endif
    endif
until mouse_click = -1

Σημαντικά σημεία:
  • drag_offset_x/y: Η απόσταση από το σημείο που πατήθηκε μέχρι την πάνω-αριστερή γωνία
  • Έλεγχος ορίων: Το block δεν βγαίνει έξω από το ταμπλό (6-35)
  • Η move μετακινεί το block στη νέα θέση


8. Collision Detection​

Κώδικας:
sub check_collision()
    local i, collision = 0
    local sel_left = selected_x
    local sel_top = selected_y
    local sel_right = selected_x + selected_w
    local sel_bottom = selected_y + selected_h

    for i = 1 to blocks_per_level[level]
        if i = selected_index then pass

        local nx = b//level//i:[].x
        local ny = b//level//i:[].y
        local nw = b//level//i:[].w
        local nh = b//level//i:[].h

        if sel_left < nx + nw and sel_right > nx and \
           sel_top < ny + nh and sel_bottom > ny
            collision = 1
            break
        endif
    next

    rets collision
ends
Αυτή είναι η κλασική υλοποίηση ελέγχου σύγκρουσης ορθογωνίων (AABB collision detection). Δύο ορθογώνια συγκρούονται αν:
  • Η αριστερή πλευρά του 1ου είναι αριστερότερα από τη δεξιά πλευρά του 2ου
  • ΚΑΙ η δεξιά πλευρά του 1ου είναι δεξιότερα από την αριστερή πλευρά του 2ου
  • (Το ίδιο για πάνω/κάτω)


9. Τα Επίπεδα (Levels)​

Κάθε επίπεδο ορίζεται με μια ετικέτα (label) και μια σειρά από type:
Κώδικας:
level1#
type b11 (x=6,  y=6,  w=4, h=14, c=1,  d=0)
type b12 (x=16, y=6,  w=9, h=4,  c=2,  d=1)
...
goto start

Το blocks_per_level[] περιέχει τον αριθμό blocks για κάθε επίπεδο:
Κώδικας:
dim blocks_per_level[] = \
    0, 11, 11, 8, 12, 11, 11, 10, 11, 9, 8, 6, 10, 9
(Το 0 στην αρχή είναι γιατί ξεκινάμε από το level 1)

Πρόσβαση στα blocks:
Κώδικας:
b//level//i:[].x  ! Πρόσβαση στο x του i-οστού block του τρέχοντος level
Το // είναι ο τελεστής συνένωσης ονομάτων (concatenation operator) στην Hobby BASIC.

Το Λευκό Block (Στόχος)​

Το λευκό block έχει c=7 (COLOR_TARGET_BLOCK). Όταν αυτό φτάσει πάνω από το EXIT_ZONE_TOP:
Κώδικας:
if (selected_color = COLOR_TARGET_BLOCK and selected_y < EXIT_ZONE_TOP)
    sound SND_WIN
    times 10 move selected_x, selected_y, selected_w, selected_h, selected_x, selected_y-1 : wait 50
    times 3000 erase RND(BOARD_WIDTH)+5, RND(BOARD_HEIGHT)+5, 1, -1, -1
    level_solved$(level) = "1"
    save path_status$, level_solved$
    goto next_level
endif

Το εφέ νίκης:
  1. Παίζει ήχο
  2. Το λευκό block κατευθύνεται αυτόματα προς την έξοδο
  3. Random κελιά σβήνουν σαν πυροτέχνημα
  4. Αποθηκεύεται η πρόοδος


10. Ολόκληρος ο Κώδικας​

Κώδικας: https://0x0.st/PQ6C.BAS


Συμπεράσματα​

Το Klotski στην Hobby BASIC είναι ένα ολοκληρωμένο παράδειγμα για:
  • Διαχείριση ποντικιού σε real-time εφαρμογή
  • Collision detection μεταξύ αντικειμένων
  • Αποθήκευση προόδου σε αρχεία
  • Πολλαπλά επίπεδα με δυναμική φόρτωση
  • Οπτικά εφέ με απλές εντολές

10 years of fun with Hobby BASIC.
 
Τελευταία επεξεργασία:
Ευχαριστώ xqtr! Η "μηχανή" του παιχνιδιού (το drag μαζί με το collision), σε καθαρό κώδικα αν αφαιρέσεις όλα τα υπόλοιπα είναι +-50 γραμμές BASIC. Και παίζει σούπερ smooth. Όχι άσχημα για έναν custom διερμηνευτή.
 
Πίσω
Μπλουζα