8-Bit-Stil springenden Ball um eine Leinwand

20

Inspiriert von diesem Eintrag aus dem Commodore 64-Benutzerhandbuch:

10 PRINT "{CLR/HOME}"
20 POKE 53280,7 : POKE 53281,13
30 X = 1 : Y = 1
40 DX = 1 : DY = 1
50 POKE 1024 + X + 40 * Y, 81
60 FOR T = 1 TO 10 : NEXT
70 POKE 1024 + X + 40 * Y, 32
80 X = X + DX
90 IF X <= 0 OR X >= 39 THEN DX = -DX
100 Y = Y + DY
110 IF Y <= 0 OR Y >= 24 THEN DY = -DY
120 GOTO 50

Erstellen Sie ein ähnliches Programm in der von Ihnen gewählten Sprache / Plattform, um ein kugelähnliches Objekt über Ihr Terminal, Ihren Bildschirm, Ihre Leinwand oder einen anderen visuellen Anzeigebereich zu werfen.

Sie müssen die PETSCII-Grafiken des C64 nicht genau nachbilden, es ist nicht einfach Ooder onicht ausreichend, und Sie müssen den GOTOBefehl auch nicht verwenden, wenn er noch in Ihrer Sprache vorhanden ist. Solange Ihr Ball oben auf Ihrer Leinwand beginnt und sich diagonal bewegt, bis er eine Leinwandbegrenzung erreicht, und dann wie folgt entsprechend abprallt:

  • Fahren Sie nach unten und rechts und berühren Sie den unteren Bildschirmrand, hüpfen Sie nach oben und fahren Sie nach rechts fort.
  • Nach rechts und oben reisen und an die äußerste rechte Grenze stoßen, nach links und oben springen;
  • Nach links und oben reisen und oben aufschlagen, nach links und unten springen;
  • Nach links und unten reisen und die äußerste linke Grenze erreichen, nach rechts und unten springen;
  • Trifft jede Ecke und kehrt die Richtung um;

Dann sind wir alle gut.

Sie müssen den Ball auch nicht um jeweils 8 Pixel bewegen, wie dies im BASIC-Listing des C64 der Fall ist. Sie können jeweils einen Zeichenblock oder ein Pixel verschieben, je nachdem, was Sie für am besten halten.

Um zu sehen, ob dieses BASIC-Listing funktioniert, können Sie es mit diesem Online-Commodore 64-Emulator eingeben, sofern Ihr Browser Flash unterstützt.

Shaun Bebbers
quelle
2
JavaScript-Zeichenfläche. D'uh.
Matthew Roh
Ich bin mir nicht sicher, wie du heutzutage einen Bildschirm nennst. Früher haben Sie nur den Bildschirm und den Randbereich durch Ihr Fernsehgerät oder Ihren Bildschirm gesehen ... und jetzt haben Sie Terminals, Fenster, Leinwände, Stdout usw. ... das ist alles sehr verwirrend für mich.
Shaun Bebbers
Es wäre besser, wenn wir einen konstanten Wert für die Pixelgröße hätten.
Matthew Roh
4
Können wir die Bildschirmgröße von 1x1 annehmen und für immer drucken?
Matthew Roh
1
mögliches Duplikat von ASCII Ball in Box Animation
Titus

Antworten:

3

6502 Maschinencode (C64), 90 89 91 Bytes

+2 Bytes , weil es muss eine Last - Adresse (nicht PIC wegen der Selbst Modifikation)

00 C0 20 44 E5 CA D0 FD C6 FC D0 F9 A2 20 86 FC A9 D8 85 9E A9 03 85 9F A4 CA
18 A5 9E 69 28 85 9E 90 02 E6 9F 88 10 F2 A4 C9 8A 91 9E C9 20 D0 08 E6 C9 E6
CA A2 51 10 D7 A5 C9 F0 04 C9 27 D0 08 AD 2F C0 49 20 8D 2F C0 A5 CA F0 04 C9
18 D0 B4 AD 31 C0 49 20 8D 31 C0 D0 AA

Online-Demo

Verwendung: sys49152

Ich habe mich sehr bemüht, die Größe zu reduzieren (z. B. ohne IRQs für das Timing, sondern mit blöden, leeren Loops), und war immer noch nicht in der Lage , das Niveau von Titus 'Golf C64 BASIC zu erreichen . Aber es sieht weniger flackernd aus;)

Erläuterung: (Vice Disassembly)

00 C0       .WORD $C000         ; load address
20 44 E5    JSR $E544           ; clear screen
CA          DEX
D0 FD       BNE $C003           ; inner wait (256 decrements)
C6 FC       DEC $FC
D0 F9       BNE $C003           ; outer wait (32 decrements in zeropage)
A2 20       LDX #$20            ; wait counter and screen code for "space"
86 FC       STX $FC             ; store wait counter
A9 D8       LDA #$D8            ; load screen base address ...
85 9E       STA $9E             ; ... -40 (quasi row "-1") ...
A9 03       LDA #$03            ; ... into vector at $9e/$9f
85 9F       STA $9F
A4 CA       LDY $CA             ; load current row in Y
18          CLC                 ; clear carry flag
A5 9E       LDA $9E             ; add ...
69 28       ADC #$28            ; ... $28 (40 cols) to ...
85 9E       STA $9E             ; ... vector
90 02       BCC $C023
E6 9F       INC $9F             ; handle carry
88          DEY                 ; count rows down
10 F2       BPL $C018
A4 C9       LDY $C9             ; load current col in Y
8A          TXA                 ; copy screen code from X to A
91 9E       STA ($9E),Y         ; store at position of screen
C9 20       CMP #$20            ; screen code was "space"
D0 08       BNE $C037           ; if not, ball was drawn
E6 C9       INC $C9             ; next column   | opcodes are modified
E6 CA       INC $CA             ; next row      | here for directions
A2 51       LDX #$51            ; screen code for "ball"
10 D7       BPL $C00E           ; and back to drawing code
A5 C9       LDA $C9             ; load current column
F0 04       BEQ $C03F           ; if zero, change X direction
C9 27       CMP #$27            ; compare with last column (39)
D0 08       BNE $C047           ; if not equal, don't change X direction
AD 2F C0    LDA $C02F           ; load opcode for X direction
49 20       EOR #$20            ; toggle between ZP INC and DEC
8D 2F C0    STA $C02F           ; store back
A5 CA       LDA $CA             ; load current row
F0 04       BEQ $C04F           ; if zero, change Y direction
C9 18       CMP #$18            ; compare with last row (24)
D0 B4       BNE $C003           ; if not equal, don't change Y direction
AD 31 C0    LDA $C031           ; load opcode for Y direction
49 20       EOR #$20            ; toggle between ZP INC and DEC
8D 31 C0    STA $C031           ; store back
D0 AA       BNE $C003           ; -> main loop

Nur zum Spaß, hier ist eine professionellere Variante, bei der ein Sprite für den Ball verwendet wird und die Grenze blinkt, wenn 385 Bytes erreicht werden (einschließlich der Sprite-Daten, die an Ort und Stelle verwendet werden ):

00 C0 AD 15 D0 F0 30 A9 CC 85 FC A9 04 20 A2 C0 A9 97 8D 00 DD A9 15 8D 18 D0 
A9 00 8D 15 D0 8D 1A D0 A2 81 8E 0D DC A2 31 8E 14 03 A2 EA 8E 15 03 58 A6 D6 
4C F0 E9 A9 04 85 FC A9 CC 20 A2 C0 A2 31 86 01 A2 10 A9 D0 85 FC B1 FB C6 01 
91 FB E6 01 C8 D0 F5 E6 FC CA D0 F0 A9 37 85 01 A9 94 8D 00 DD A9 35 8D 18 D0 
8D 27 D0 A2 05 8E F8 CF A2 01 8E 15 D0 8E 1A D0 8E 12 D0 86 FD 86 FE A2 18 8E 
00 D0 A2 1B 8E 11 D0 A2 32 8E 01 D0 A2 7F 8E 0D DC AE 0D DC AE 20 D0 86 FB A2 
C1 8E 14 03 A2 C0 D0 8A 85 FE 8D 88 02 A9 00 85 FB 85 FD A2 04 A0 00 78 B1 FB 
91 FD C8 D0 F9 E6 FC E6 FE CA D0 F2 60 A6 FB 8E 20 D0 CE 19 D0 A5 FD F0 20 AD 
00 D0 18 69 04 8D 00 D0 90 03 EE 10 D0 C9 40 D0 2C AD 10 D0 29 01 F0 25 20 38 
C1 C6 FD F0 1E AD 00 D0 38 E9 04 8D 00 D0 B0 03 CE 10 D0 C9 18 D0 0C AD 10 D0 
29 01 D0 05 20 38 C1 E6 FD A5 FE F0 14 AD 01 D0 18 69 04 8D 01 D0 C9 E6 D0 19 
20 38 C1 C6 FE F0 12 AD 01 D0 38 E9 04 8D 01 D0 C9 32 D0 05 20 38 C1 E6 FE 4C 
31 EA A9 01 8D 20 D0 60 00 00 00 7E 00 03 FF C0 07 FF E0 1F FF F8 1F FF F8 3F 
FF FC 7F FF FE 7F FF FE FF FF FF FF FF FF FF FF FF FF FF FF 7F FF FE 7F FF FE 
3F FF FC 1F FF F8 1F FF F8 07 FF E0 03 FF C0 00 7E 00 00 00 00 

Online-Demo - | - durchsuchen Sie die ca65 Assembler-Quelle

Starten und stoppen Sie den springenden Ball mit sys49152.

  • Dadurch bleibt der C64 BASIC aktiv, indem der VIC-II-Adressraum nach oben verschoben wird. Dazu $C000müssen der Bildschirminhalt und der Zeichensatz (Schriftart) kopiert werden.
  • Es wird an den System-IRQ angeschlossen, und um Flimmern zu vermeiden, wird die Quelle dieses IRQs auf den VIC-II-Grafikchip geändert, sodass Aktualisierungen immer zwischen Frames erfolgen.
  • Glitches:
    1. RUN/STOP + RESTORE ist kaputt, versuche es nicht.
    2. Mit dem VIC-II als IRQ-Quelle blinkt der Cursor etwas langsamer und TI$bleibt ebenfalls zurück.
    3. Wenn Sie anhalten, während der Rand blinkt (sehr unwahrscheinlich, aber möglich), bleibt er weiß - Sie müssen ihn manuell wiederherstellen.
Felix Palmen
quelle
1
Es ist nicht völlig unabhängig, oder? Ich sehe zwei absolute LDAs und zwei STAs. Trotzdem großartige Arbeit!
Titus
Verdammt du hast recht: o Ich habe die Selbstmodifikation vergessen! Ich werde aktualisieren, sobald ich auf dem PC bin.
Felix Palmen
1
@ Titus behoben ... und nur zum Spaß, fügte eine "bessere" Variante :)
Felix Palmen
Hast du darüber nachgedacht, das Sprite zu packen? (Hmm ... verwenden Sie das charset ROM?) Und Id lieber inc $d020über jsr flash;) hitshimselfwithalargetrout Es ist wunderbar!
Titus
1
@Titus würde 2 Bytes sparen, ja. Die Ladeadresse ist Teil einer gültigen .prgDatei und von meiner Meta-Frage hier aus muss ich sie einschließen ... könnte sie wahrscheinlich weglassen, wenn der Code positionsunabhängig wäre.
Felix Palmen
14

Bash + Unix-Dienstprogramme, 125 117 Bytes

for((x=y=u=v=1;;x+=u,y+=v,u=(x<1||x>=`tput cols`-1)?-u:u,v=(y<1||y>=`tput lines`-1)?-v:v)){
tput cup $y $x
sleep .1
}

Animation des Probelaufs:

Animation des Probelaufs

Mitchell Spector
quelle
6
Es traf die genaue Ecke! : O
mbomb007
11

CP-1610- Baugruppe, 6764 62 DECLEs = 78 Byte

Dieser Code soll auf einer Intellivision ausgeführt werden . Es verwendet eines seiner Hardware-Sprites, das als MOB (for Mobile Object) bezeichnet wird.

Ein CP-1610-Opcode wird mit einem 10-Bit-Wert codiert, der als "DECLE" bezeichnet wird. Dieses Programm ist 62 DECLE lang und beginnt bei 4800 US-Dollar und endet bei 483 D-Dollar.

Hexadezimaler Speicherauszug + Quelle

                            ROMW  10            ; use 10-bit ROM
                            ORG   $4800         ; start program at address $4800

                    FRAME   EQU   $17E          ; frame #

                            ;; ------------------------------------------------ ;;
                            ;;  main entry point                                ;;
                            ;; ------------------------------------------------ ;;
                    main    PROC

4800 0001                   SDBD                ; load Interrupt Service Routine
4801 02B8 002B 0048         MVII  #isr,   R0    ; into R0

4804 0240 0100              MVO   R0,     $100  ; update ISR
4806 0040                   SWAP  R0
4807 0240 0101              MVO   R0,     $101

4809 02B9 0208              MVII  #$0208, R1    ; initialize R1 = X
480B 02BA 0108              MVII  #$0108, R2    ; initialize R2 = Y
480D 02BB 0001              MVII  #1,     R3    ; initialize R3 = DX
480F 009C                   MOVR  R3,     R4    ; initialize R4 = DY

4810 0002                   EIS                 ; enable interrupts

                            ;; ------------------------------------------------ ;;
                            ;;  main loop                                       ;;
                            ;; ------------------------------------------------ ;;
4811 0280 017E      @@loop  MVI   FRAME,  R0    ; R0 = current frame #

4813 0340 017E      @@spin  CMP   FRAME,  R0    ; wait for next frame
4815 0224 0003              BEQ   @@spin

4817 00D9                   ADDR  R3,     R1    ; X += DX

4818 0379 02A0              CMPI  #$2A0,  R1    ; reached right border?
481A 0204 0003              BEQ   @@updDx

481C 0379 0208              CMPI  #$208,  R1    ; reached left border?
481E 002F                   ADCR  PC

481F 0023           @@updDx NEGR  R3            ; DX = -DX

4820 00E2                   ADDR  R4,     R2    ; Y += DY

4821 037A 0160              CMPI  #$160,  R2    ; reached bottom border?
4823 0204 0003              BEQ   @@updDy

4825 037A 0108              CMPI  #$108,  R2    ; reached top border?
4827 002F                   ADCR  PC

4828 0024           @@updDy NEGR  R4            ; DY = -DY

4829 0220 0019              B     @@loop        ; loop forever

                            ENDP

                            ;; ------------------------------------------------ ;;
                            ;;  ISR                                             ;;
                            ;; ------------------------------------------------ ;;
                    isr     PROC

482B 01DB                   CLRR  R3            ; clear a bunch of STIC registers
482C 02BC 0020              MVII  #$20,   R4

482E 0263           @@clear MVO@  R3,     R4    ; (including background color,
482F 037C 0032              CMPI  #$32,   R4    ; border color, etc.)
4831 0226 0004              BLE   @@clear

4833 0259                   MVO@  R1,     R3    ; update X register of MOB #0
4834 0242 0008              MVO   R2,     $8    ; update Y register of MOB #0
4836 02BB 017E              MVII  #$017E, R3    ; update A register of MOB #0
4838 0243 0010              MVO   R3,     $10   ; (using a yellow "O")

483A 0298                   MVI@  R3,     R0    ; increment frame #
483B 0008                   INCR  R0
483C 0258                   MVO@  R0,     R3

483D 00AF                   JR    R5            ; return from ISR

                            ENDP

Ausgabe

Ausgabe

Arnauld
quelle
10

HTML (Microsoft Edge / Internet Explorer), 81 Byte

Stellen Sie sich vor, es wäre 1998 mit diesen verschachtelten <marquee>Tags:

<marquee behavior=alternate direction=down><marquee behavior=alternate width=99>O

Getestet in Microsoft Edge, aber von dem, was ich gelesen habe, sollte IE auch noch Zelte unterstützen. Funktioniert entschieden nicht in Chrome.

Die Einstellung direction=upwürde 2 Bytes sparen, aber die Regel, dass der Ball oben auf der Leinwand beginnen muss, verletzen.

Jack Brounstein
quelle
Leider ist dies eine ungültige Antwort, da sich der Ball nicht diagonal bewegt, wie es die Herausforderung erfordert.
El'endia Starman
Haben Sie es in Microsoft Edge versucht? Chrome scheint das directionAttribut nicht zu unterstützen .
Jack Brounstein
Huh, ich entschuldige mich - es funktioniert in Edge. Ich kann bestätigen, dass es in Chrome nicht funktioniert, und ich kann bestätigen, dass es in Firefox und Internet Explorer funktioniert. Drei von vier ist nicht schlecht (und Sie brauchen nur eine, damit diese Antwort gültig ist). +1
El'endia Starman
1
+1 für marquee, das ist ziemlich kreativ!
Metoniem
Hat für mich in Chrome gearbeitet.
ckjbgames
8

TI-BASIC, 71, 70

1->A
1->B
1->C
1->D
While 1
ClrHome
Output(B,A,0
A+C->A
B+D->B
If A<2 or A>15
~C->C
If B<2 or B>7
~D->D
End

Ziemlich wörtliche Übersetzung, ich wäre nicht überrascht, wenn es Tricks gibt, um es kleiner zu machen.

Der Bildschirm ist 16x8 und 1-indiziert, sodass die Konstanten unterschiedlich sind.

~ ist der SourceCoder-Weg, um das Negationssymbol zu schreiben.

GIF des Springens O

Bei Hardware sieht es flüssiger aus.

Harold
quelle
Sind Sie sicher, dass dies 70 Bytes sind? Es sieht nach weniger aus.
12. Mai, 21.
@ 12Me21 Wie viele Bytes zählen Sie? Ich erhalte 80 Bytes, wenn ich dies auf einem Taschenrechner speichere, und 10 Bytes für ein leeres Programm, das mit meiner Zählung übereinstimmt.
Harold
Oh, dann habe ich wohl falsch gezählt.
12. Mai, 21.
7

Befunge, 209 Bytes

>10120130pppp>"l52?[J2["39*,,,,39*,,,,,,v
v+56/+55\%+55:+1g01*83-"6!"7\-"6!?"8-*86<
>00g1+:55+%\55+/"+!6"-48*,68>*#8+#6:#,_v$
v:+g03g01p02+-\g02*2!-*64\*2!:p00:+g02g<$
>10p:!2*\"O"-!2*30g\-+30p"2"::**>:#->#1_^

Dies setzt eine Bildschirmgröße von 80x25 voraus, aber Sie können den Bereich leicht optimieren, indem Sie die "O"(79) in der letzten Zeile und die *64(24) in der vorletzten Zeile ersetzen (beachten Sie, dass die vorletzte Zeile von rechts nach links ausgeführt wird). Die Geschwindigkeit kann auch durch Ersetzen von "2"(50) in der letzten Zeile angepasst werden .

James Holderness
quelle
7

Java, 184 176 Bytes

class A{public static void main(String[]a)throws Exception{for(int X=1,Y=1,x=1,y=1;;System.out.print("\033["+X+";"+Y+"H"),Thread.sleep(50),X+=x=X%25<1?-x:x,Y+=y=Y%85<1?-y:y);}}

Dies verwendet ANSI-Escape-Sequenzen , um den Cursor zu verschieben, der das Objekt ist, das um eine 85 x 25Terminalanzeige herum springt . Speichern Sie in einer Datei mit dem NamenA.java .

Ungolfed

class Terminal_Bouncing_Ball {
    public static void main(String[] args) throws InterruptedException {
        int X = 0, Y = 0, dx = 1, dy = 1;
        while (true) {
            System.out.print(String.format("\033[%d;%dH",X,Y));
            Thread.sleep(50);
            dx = (X < 1) ? 1 : (X > 71) ? -1 : dx;
            dy = (Y < 1) ? 1 : (Y > 237) ? -1 : dy;
            X += dx;
            Y += dy;
        }
    }
}

Demo

Beispiel

R. Kap
quelle
Dies ist Codegolf, daher sollten Sie es entfernen Thread.sleep(50). Und Ihre Golf- und Nicht-Golf-Programme stimmen nicht überein.
Jakob
4

Clojure, 398 380 375 Bytes

(ns g(:require[quil.core :as q]))(def w 1e3)(def h 1e3)(def f 100)(def b(atom{:x f :y f :n 1 :m 1}))(q/defsketch . :size[w h]:setup #(do(q/text-font(q/create-font""f))(q/fill 255 255 255)):draw #(let[s 9{x :x y :y n :n m :m}@b c(+ x(* n s))u(+ y(* m s))](q/background 0 0 0)(reset! b{:x c :y u :n(if(< 0 c(- w f))n(* -1 n)):m(if(<(+ 0 f)u h)m(* -1 m))})(q/text"O"(:x @b)(:y @b))))

-18 Bytes, indem Sie den Namen der Schriftart in eine leere Zeichenfolge ändern, um sie als Standard festzulegen, die Begrenzungsüberprüfungen einzufügen und das untere Begrenzungsproblem (das Sie im GIF sehen können) zu beheben. Behebung der tatsächlich gespeicherten Bytes.

-5 Bytes, indem Sie zu einer prägnanteren Destrukturierungssyntax wechseln und den Ball um ein Pixel verkleinern.

Verwendet Quil .

Ich habe versucht, in den Funktionsmodus zu wechseln, aber es war viel zusätzlicher Code erforderlich, und es wurde teurer.

(ns bits.golf.ball-bounce
  (:require [quil.core :as q]))

(def width 1000)
(def height 1000)

(def font-size 100)

; Mutable state holding the properties of the ball. n and m are the directions on the x and y axis.
(def ball (atom {:x 300 :y 600 :n 1 :m 1}))

(q/defsketch b
  :size [width height] ; Window size

  :setup #(do
            (q/text-font (q/create-font "Arial" font-size)) ; Set the font
            (q/fill 255 255 255)) ; And the text color

  :draw
  #(let [speed 9
         ; Deconstruct the state
         {:keys [x y n m]} @ball
         next-x (+ x (* n speed))
         next-y (+ y (* m speed))

         ; I'm adding/subtracting the font-size so it stays in the window properly
         x-inbounds? (< 0 next-x (- width font-size))
         y-inbounds? (< (+ 0 font-size) next-y height)]

     ; Wipe the screen so the ball doesn't smear
     (q/background 0 0 0)

     ; Reset the state
     (reset! ball
             {:x next-x
              :y next-y
              :n (if x-inbounds? n (* -1 n))
              :m (if y-inbounds? m (* -1 m))})

     ; Draw the ball
     (q/text "O" (:x @ball) (:y @ball))))

Ball, der GIF aufprallt

(Beachten Sie, dass die neue Version nicht wie im GIF früh am unteren Bildschirmrand abfällt.)

Karzigenat
quelle
Mir ist gerade klar geworden, dass ich (+ 0 font-size)da drin bin . Das ist peinlich. Ich werde das in der nächsten Version beheben. Sollte mich wie 5 Bytes retten.
Carcigenicate
4

Schläger 247 Bytes

(let*((w 500)(h(* w 0.6))(x 100)(y 0)(d 10)(e d)(G(λ(t)(set! x(+ x d))(when(or(> x w)(< x 0))
(set! d(* d -1)))(set! y(+ y e))(when(or(> y h)(< y 0))(set! e(* e -1)))
(underlay/xy(rectangle w h"solid""white")x y(circle 10"solid""black")))))(animate G))

Ungolfed:

(require 2htdp/image
         2htdp/universe) 

(let* ((wd 500)            ; define variables and their initial values
       (ht 300)
       (x 100)
       (y 0)
       (dx 10)
       (dy 10)

       (imgfn              ; define function to draw one frame; called repeatedly by animate fn; 
        (λ (t)             ; t is number of ticks till now- sent by animate fn; ignored here;

                           ; update location (x and y values):
          (set! x (+ x dx))
          (when (or (> x wd) (< x 0))
            (set! dx (* dx -1)))             ; invert direction at edges
          (set! y (+ y dy))
          (when (or (> y ht) (< y 0))
            (set! dy (* dy -1)))             ; invert direction at edges

                           ; draw image: 
          (underlay/xy
           (rectangle wd ht "solid" "white") ; draw background
           x y                               ; go to location (x,y)
           (circle 10 "solid" "black")       ; draw ball
          ))))

  (animate imgfn))         ; animates the images created by imgfn (default rate 28 times/sec)

Ausgabe:

Bildbeschreibung hier eingeben

rnso
quelle
1
Racquetball spielen mit Racket!
ckjbgames
Das ist gut!
RNSO
"Racket" leitet sich aus der Programmiersprache "Scheme" ab: Nach "Scheme" (einem abwegigen Plan) folgt "Racket" (ein Betrug oder Schwindel)!
rnso
@mso Noch besser!
ckjbgames
3

Jelly, 37 Bytes

“ñc‘Ọ24ḶŒḄṖ⁸ị⁷x⁸µ80ḶŒḄṖ⁸ị⁶x⁸‘œS.1
Ç1¿

Mit etwas Hilfe aus dieser Antwort , um die Schleifen- und Fluchtzeichen richtig zu machen. Momentan springt es auf einem 80x24-Bildschirm herum, aber das kann im Code leicht geändert werden.

Die Koordinaten in jeder Richtung können als Elemente von zwei Listen [0, 1,..., 24, 23,..., 1]und dargestellt werden[0, 1,..., 80, 79,..., 1] , nennen wir sie Yund X, die sich unendlich wiederholen. Diese unendliche Wiederholung kann mithilfe der modularen Indizierung emuliert werden - mithilfe von Jelly. Beispiel: In der iIteration befindet sich der Ball auf Position (X[i%|X|], Y[i%|Y|]) = (iịY, iịX). Die sich bewegende Kugel ist nur der Cursor, der durch das Aussenden von iịYZeilenumbrüchen und iịXLeerzeichen in Position gebracht wird.

Demo

https://i.gyazo.com/b8eac64097cb6d3a18185877c2f4c945.gif

Erläuterung

“ñc‘Ọ24ḶŒḄṖ⁸ị⁷x⁸µ80ḶŒḄṖ⁸ị⁶x⁸‘œS.1        Monadic helper link - argument i.
                                         Resets the terminal, prints Y[i] newlines,
                                         X[i] spaces and returns i + 1.
“ñc‘                                     Set the output to [27, 99]
    Ọ                                    Convert to characters and print (\x1bc)
                                          -> Cursor is at position (0,0)
     24Ḷ                                 Lowered range of 24. Yields [0,...,23].
        ŒḄ                               Bounce. Yields [0,...,23,22,...,0].
          Ṗ                              Pop. Yields [0,...,23,22,...,1] = Y.
           ⁸ị                            Modular index i (⁸) into Y. The current
                                         value is the Y coordinate, y.
              x                          Repeat y times
             ⁷                           the newline character ('\n').
               ⁸                         Output that (y times '\n') and continue
                                         with value i.
                                          -> Cursor is at position (0, y)
                µ                        Monadic chain separation.
                 80ḶŒḄṖ                  Same as above, but this time yielding X.
                       ⁸ị                Modular index i into X, yielding the
                                         value for x.
                          x              Repeat x times
                         ⁶               the whitespace character.
                           ⁸             Output that (x times ' ') and continue
                                         with value i.
                                         -> Cursor is at position (x, y), the
                                            final position.
                             œS.1        Wait 0.1 seconds.
                            ‘            Return i + 1.

Ç1¿                                      Main (niladic) link.
 1¿                                      While true.
Ç                                        Call the helper link. The first time
                                         there is no argument and i will be [],
                                         which is cast to 0 when used as integer
                                         (e.g. try ‘¶Ç). After that, the previous
                                         return value (i + 1) is used.
PidgeyUsedGust
quelle
2

SmileBASIC, 85 74 Bytes

SPSET.,9M=MAINCNT
SPOFS.,ASIN(SIN(M/5))*122+192,112+71*ASIN(SIN(M/3))EXEC.

Die Position des Balls kann mit 2 Dreieckswellen modelliert werden, und der kürzeste Weg, sie in SmileBASIC zu erzeugen, war Arkussinus (Sinus (x)). (Der Algorithmus mit MOD war länger, da SB MODanstelle von verwendet %)

12Me21
quelle
2

CSS / HTML, 200 + 7 = 207 Bytes

p{position:relative}a{position:absolute;animation:infinite linear alternate;animation-name:x,y;animation-duration:7.9s,2.3s}@keyframes x{from{left:0}to{left:79ch}}@keyframes y{from{top:0}to{top:24em}}
<p><a>O

Diese Version zeigt Ihnen die Größe der Leinwand und verleiht der Animation ein pixeligeres Gefühl:

Neil
quelle
2

Dyalog APL, 44 Bytes

{⎕SM∘←0,G←⍺+⍵⋄G∇⍵×1-2×⊃1 G∨.≥G⎕SD⊣⎕DL.1}⍨1 1

Erläuterung:

  • {...}⍨1 1 : rufe die angegebene Funktion mit ⍺ = ⍵ = 1 1 auf
    • ⎕SM∘←0,G←⍺+⍵: speichern ⍺+⍵in G, zeige ein 0an diesem Ort im⎕SM Fenster .
    • ⎕DL.1: Warten Sie eine Zehntelsekunde
    • ⊃1 G∨.≥G⎕SDWenn Check: Gist an der ⎕SMFenstergrenze ( 1≥Goder G≥⎕SD, ⎕SDist die s creen d bmessungen)
    • 1-2×: Karte [1,0]auf[¯1,1] , um die Fahrtrichtung umzudrehen
    • ⍵×: multipliziere die aktuelle Fahrtrichtung damit
    • G∇: Rekursion, sei Gder neue Ort ( ) und ⍵....sei die neue Richtung ( ).
Marinus
quelle
Soll das Terminal während des Betriebs ständig geöffnet und geschlossen werden? Es ist ziemlich schwierig, dies zu stoppen, sobald es gestartet wurde, da das Terminal alle Zehntelsekunden geschlossen und wieder geöffnet wird (zumindest unter Windows).
Ren
1
@wptreanor: fixed
marinus
coole, exzellente Arbeit!
Ren
2

PHP 112 97 94 103 102 Bytes

for(;;usleep(1e5),$i%=624)echo($r=str_repeat)(A^K,99),$r(A^a,abs($i%78-39)),O,$r(A^K,abs($i++%48-24));

Bounces ein Kapital Oin einem 40x25-Raster, beginnend in der oberen rechten Ecke;
druckt 99 Zeilenumbrüche, um den Bildschirm zu löschen.

Laufen Sie mit -nr.

A^K= chr(10)= newline
A^a= chr(32)= Leerzeichen

Titus
quelle
1
Hallo Titus, ich bin es wieder. for($d=$e=-1;;usleep(1e5))echo($r=str_repeat)(A^K,99),$r(A^a,$x+=$d*=$x%79?1:-1),O,$r(A^K,$y+=$e*=$y%24?1:-1);. Das Modulo ist bei 0 und N falsch und kehrt die Richtung um. Leider müssen wir $ d und $ e auf -1 setzen, aber wir bekommen trotzdem einige Einsparungen. $x%79<=>.5funktioniert auch für die gleichen Bytes.
Christoph
1
Hey @Christoph, willkommen zurück. Merkwürdig: Als ich deine Sachen kopierte, hatte sie 116 Bytes anstatt 110. Aber es inspirierte mich zu etwas viel kürzerem.
Titus
Wir sind auf jeden Fall ein gutes Team;) Merkwürdige Sache beim Kopieren Ich habe keine Ahnung warum.
Christoph
2

Simons BASIC (C64), 66 65 Bytes

Ein Byte gespart dank @ShaunBebbers.

Ich brauche hier nur eine Zeile, weil Simons 'Basic eine Modulofunktion hat.
Um dies zu erreichen, benötigen Sie einen physischen C64 und ein Simons BASIC-Modul
(oder eine andere BASIC-Erweiterung, die eine modFunktion hat).

0fori=0to623:print"{CLR}":poke1024+40*abs(mod(i,48)-24)+abs(mod(i,78)-39),81:next:goto

Geben Sie diese 69 Zeichen ein:

0fOi=0TO623:?"{CLR}":pO1024+40*aB(mod(i,48)-24)+aB(mod(i,78)-39),81:nE:gO

{CLR}ist PETSCII 147, die den Bildschirm löscht. Verwenden Sie Shift + CLR / HOME, um es einzugeben.

bytecount

Beim Speichern auf der Festplatte werden 65 Byte benötigt, da die Befehle mit einem Token versehen sind:
for , to, poke, abs, nextund gotosind jeweils ein Byte; modnimmt zwei Bytes.
Das sind 59 Byte Code plus 4 Byte für Zeiger und 2 Byte für die Zeilennummer.

Informationen hierzu finden Sie unter Zuordnen des C64 und Suchen nach $800(BASIC-Programmtext).
(Den Speicherbereich für den Videobildschirm finden Sie unter $400.)

Nervenzusammenbruch

Das Programm durchläuft eine Schleife Ivon 0 bis 623 (= LCM von 48 und 78 minus 1). In der Schleife

  • Der Bildschirm wird gelöscht
  • I wird auf 39..0..38 bzw. 24..0..23 abgebildet
  • und der Blob (PETSCII 81) wird an der entsprechenden Position im Videospeicher abgelegt
    (wie es das ursprüngliche Programm tut).

Wenn die Schleife beendet ist, wird das Programm neu gestartet, indem in Zeile 0 gesprungen wird.

C64 BASIC, 77 76 Bytes

0fori=0to623:print"{CLR}"
1poke1024+40*abs(i-48*int(i/48)-24)+abs(i-78*int(i/78)-39),81:next:goto

Leider brauche ich zwei Zeilen, denn selbst mit allen möglichen Abkürzungen würde es 83 Zeichen dauern - zu viele, um den C64-Zeileneditor zu verwenden:

0fOi=0to623:?"{CLR}":pO1024+40*aB(i-48*int(i/48)-24)+aB(i-78*int(i/78)-39),81:nE:gO

(Ein Hex-Editor könnte verwendet werden, um eine längere Zeile zu erstellen - was 73 Byte ergeben würde.)

Titus
quelle
1
Commodore-Befehlstrennzeichen sind :und nicht;
Shaun Bebbers
1
Auch wenn Sie bei Zeile Null anfangen, können Sie einfach gotoin Ihrer zweizeiligen Version verwenden, wie es bei BASIC 2gotogoto 0
Shaun Bebbers
Wenn Sie mehr Befehle für Ihre C64 BASIC-Liste erhalten möchten, geben Sie diese in einen C128 im 128-Modus ein, speichern Sie sie auf der Festplatte und laden Sie sie zurück in den C64-Modus. Der C128 ist standardmäßig auf 160 Zeichen begrenzt, sodass diese Barriere durchbrochen werden kann Verwenden von Commodore-Schlüsselwortabkürzungen.
Shaun Bebbers
@ ShaunBebbers gut zu wissen. Das ist so lange her. Ich wollte dies auch in Maschinencode implementieren ... und dabei versuchen, die Kernel-Routinen noch einmal zusammenzufassen. Ich bin mir nicht sicher, wann ich welche Register sichern muss. Die vollständige Kernel-Auflistung ist online . Ich kann mir einfach nicht die Zeit nehmen, weiter zu graben. Möchten Sie dies abschließen ?
Titus
Ich wollte eine MC-Version machen, obwohl ich denke, dass es selbst für mich übermäßig nachsichtig wäre, sie meiner eigenen Herausforderung zu unterwerfen. Der schnellste Weg wäre, das Byte von $0400bis direkt auf den Bildschirm zu schreiben $07e7. oder verwende Sprites. Die Verwendung des Kernal mit $ffd2(Ausgabeakkumulator) würde funktionieren, da Sie die X- und Y-Position des Cursors leicht genug einstellen können (ich erinnere mich nicht an den Aufruf dafür), aber Sie müssen möglicherweise die letzte Zeichenposition vermeiden, falls sie erzwungen wird ein Zeilenvorschub.
Shaun Bebbers
1

Python 2, 176 168 Bytes

Dies setzt eine Terminalgröße von 80x24 voraus. Auf jeden Fall nicht optimal, aber ich bin neu im Golfen, ja.

import time;x=y=d=e=1
while 1:
 m=[[' 'for i in' '*80]for j in' '*24];x+=d;y+=e;m[y][x]='O';time.sleep(.1)
 if x%79<1:d=-d
 if y%23<1:e=-e 
 for r in m:print''.join(r)

Vielen Dank an R. Kap, der x% 79 <1 anstelle von x <1oder x> 79 vorgeschlagen hat, und dasselbe gilt für y.

Tristan Batchler
quelle
Sie können ein paar Bytes speichern durch den Austausch x<1or x>78mit x%79<0und y<1or y>22mit y%23<1.
R. Kap
1

Rebol / View, 284 266 Bytes

rebol[]p: 3x9 d:[3 3]view layout[b: box blue 99x99 effect[draw[circle p 2]]rate :0.01 feel[engage: func[f a e][if a = 'time[case/all[p/x < 2[d/1: abs d/1]p/y < 2[d/2: abs d/2]p/x > 98[d/1: negate d/1]p/y > 98[d/2: negate d/2]]p/x: p/x + d/1 p/y: p/y + d/2 show b]]]]

Ungolfed:

rebol []

p: 3x9     ;; starting position
d: [3 3]   ;; direction

view layout [
    b: box blue 99x99 effect [
        draw [
            circle p 2
        ]
    ]

    rate :0.01 feel [
        engage: func [f a e] [
            if a = 'time [
                case/all [
                    p/x < 2  [d/1: abs d/1]
                    p/y < 2  [d/2: abs d/2]
                    p/x > 98 [d/1: negate d/1]
                    p/y > 98 [d/2: negate d/2]
                ]
                p/x: p/x + d/1
                p/y: p/y + d/2
                show b
            ]
        ]
    ]
]
draegtun
quelle
1

C 294 Bytes

#include<graphics.h> f(){int d=0;g,x,y,a=0,b=0;initgraph(&d,&g,NULL);x=30;y=30;while(1){x+=6;y+=7;if(y<60)b=0;if(x<60)a=0;if((y>getmaxy()-40)) b=!b;if((x>getmaxx()-40))a=!a;if(b){y-=18;x+=3;}if(a){x-=15;y+=2;}usleep(10000);setcolor(4);cleardevice();circle(x, y,30);floodfill(x,y,4);delay(45);}}

Ungolfed-Version:

#include<graphics.h>
void f()
{
 int d=DETECT,g,x,y,r=30,a=0,b=0;
 initgraph(&d,&g,NULL);
 x=30;
 y=30;

 while(1)
 {
   x+=6;
   y+=7;

   if(y<60)
     b=0;
   if(x<60)
     a=0;     

   if((y>getmaxy()-40))
        b=!b;

   if((x>getmaxx()-40))
        a=!a;

    if(b)
    {       
        y-=18;
        x+=3;
    }

    if(a)
    {       
       x-=15;
       y+=2;               
    } 
    usleep(10000);
    setcolor(RED);
    cleardevice();
    circle(x,y,r);
    floodfill(x,y,RED);
    delay(45);

  }   

}

Erläuterung

  • Um damit zu beginnen, musste ich graphics.hin mein /usr/includeVerzeichnis gelangen. Deshalb habe ich gesucht und dies ist das, was ich gefunden habe. Es ist eine TurboC Graphics-Implementierung mit SDL für Linux. Man könnte auch OpenGL verwenden. In Windows ist es vermutlich bereits installiert, was MacOS betrifft.
  • void initgraph(int *graphdriver, int *graphmode, char *pathtodriver);Initialisiert das System und versetzt es in einen Grafikmodus. In diesem Fall wird der Grafiktreiber automatisch erkannt. Bitte verweisen Sie auf diesen LinkWeitere Informationen finden .
  • x und y sind Koordinaten, die die Position des Balls bestimmen.
  • a und b sind Flags, awird auf Null gesetzt, wenn der xWert unter 60 fällt, und bwird auf Null gesetzt, wenny unter 60 fällt.
  • Die Flaggen werden umgeschaltet, wenn xundy überschreitet Grenzwerte des Fensters, und die Koordinaten werden entsprechend angepasst.
  • Ich setze ein, usleepdamit meine CPU nicht gestresst wird.
  • Normalerweise sollte man a verwenden closegraph() Anruf , um das Fenster zu schließen. Aber hier fehlt es.

Muss mit dem Linker Flag übersetzt werden -lgraph

Auf echter Hardware läuft es flüssiger. :)

Rote Kugel aufprallen

Abel Tom
quelle
Sind zum Ausführen dieses Programms Importanweisungen erforderlich?
Kritixi Lithos
@KritixiLithos Ja, Sir; Aktualisiert! Sie müssen einschließen graphics.h. Diese Antwort auf askubuntu.com/questions/525051/… war hilfreich.
Abel Tom
1

MATL , 42 Bytes

1thXH_XI`Xx8E70hZ"79HZ}&(DH4M\1>EqI*XIH+XH

Dies verwendet einen 70 × 16-Bildschirm und Zeichen O. Wenn Sie auf ein paar Bounces warten, sehen Sie den Ball an einer Ecke.

Probieren Sie es bei MATL Online!

Die Bildschirmgröße kann im Code leicht geändert werden. Der relevante Teil ist8E70 , der drückt 8, verdoppelt und drückt 70. Beispiel: Bei einem 80 × 25-Bildschirm wird durch ersetzt 5W80, wodurch er gedrückt 5, quadriert und gedrückt 80(oder durch ersetzt) ​​wird25 80 , dies erfordert jedoch ein weiteres Byte).

Auch das Hinzufügen tD am Ende des Codes wird auch die aktuelle Position in Echtzeit angezeigt (vertikal, dann horizontal, 1 1oben links). Als Beispiel für einen 80×18Bildschirm,

1thXH_XI`Xx9E80hZ"79HZ}&(DH4M\1>EqI*XIH+XHtD

Probieren Sie es auch aus!

Erläuterung

Dies verwendet eine Endlosschleife. Position wird in der Zwischenablage gehaltenH als 1 × 2-Vektor in der Zwischenablage und die Richtung Ials 1 × 2-Vektor mit den Einträgen 1oder in der Zwischenablage gespeichert -1.

Jede Iteration löscht den Bildschirm, definiert eine Matrix von Leerzeichen und schreibt ein O an der entsprechenden Position und zeigt sie an. Dann müssen Position und Richtung aktualisiert werden.

Die Position ist 1-basiert, und daher sind die Ränder des Bildschirms 1und die maximale Bildschirmgröße. Also, wenn Position Modulo Bildschirmgröße gibt0 oder 1entweder in der ersten oder zweiten Komponente , was bedeutet, dass wir eine vertikale oder horizontale Kante erreicht haben, wird diese Komponente des Richtungsvektors negiert. Danach wird die neue Richtung zur aktuellen Position hinzugefügt, um die neue Position zu erhalten.

Luis Mendo
quelle
1

Hier ist die Auflistung von ZX Spectrum.

  10 FOR n=0 to 7
  20 READ a: POKE USR "a"+n, a
  30 NEXT n
  40 DATA 60,126,243,251,255,255,126,60
  50 LET x=10:LET y=10:LET vx=1: LET vy=1
  60 PRINT AT y,x;"\a"
  70 IF x<1 OR x>30 THEN LET vx=-vx
  80 IF y<1 OR x>20 THEN LET vy=-vy
  90 LET x=x+vx: LET y=y+vy
 100 PRINT AT y-vy,x-vx;" ": GO TO 60
DrIB
quelle
Netter erster Eintrag DrlB - kannst du bitte eine Byteanzahl angeben. Ich gehe davon aus, dass dies auf jedem Speccy einschließlich 16K-Maschinen funktioniert.
Shaun Bebbers
Hallo, das sind 201 Bytes, Sie könnten die ersten 4 Zeilen weglassen, aber dann erhalten Sie nur ein springendes "a" -Zeichen, aber Sie sparen 64 Bytes. Ich werde versuchen zu optimieren. Dies ist überhaupt nichts
Besonderes
Ok, ich habe es geschafft, es auf 185 zu reduzieren, indem ich die Linien ein wenig verdichtete, ohne die Kugelgrafiken fallen zu lassen. Es ist zwar ein bisschen weniger lesbar, aber es ist schneller.
DrIB
1

C + Flüche, 190 Bytes

#include<curses.h>
w;h;x;y;d;main(e){initscr();curs_set(0);getmaxyx(stdscr,h,w);for(d=e;;usleep(20000),mvaddch(y,x,32)){mvaddch(y+=d,x+=e,48);if(!y||y>h-2)d=-d;if(!x||x>w-2)e=-e;refresh();}}

Erläuterung:

#include<curses.h>
w;h;x;y;d;
main(e)
{
    initscr();
    curs_set(0);
    getmaxyx(stdscr,h,w);

    // initialize distances to 1 (e is 1 when called without arguments)
    // wait for 1/5 second, then write space character at current pos
    for(d=e;;usleep(20000),mvaddch(y,x,32))
    {
        // advance current pos and write ball character (`0`)
        mvaddch(y+=d,x+=e,48);

        // check and change direction:
        if(!y||y>h-2)d=-d;
        if(!x||x>w-2)e=-e;

        // trigger output to screen:
        refresh();
    }
}
Felix Palmen
quelle
1

Lua ( LÖVE 2D ), 130 Bytes

x,y,a,b=0,0,1,1
function love.draw()a=(x<0 or x>800)and-a or a
b=(y<0 or y>600)and-b or b
x=x+a
y=y+b
love.graphics.points(x,y)end

Lua ist nicht die beste Sprache, wenn es um Code-Golf geht, aber los geht's! Einige erwähnenswerte Punkte:

  • Die Standardgröße für die Leinwand ist 800 x 600. Sie kann in der Konfigurationsdatei geändert werden, es wurden jedoch keine Größenbeschränkungen festgestellt. Daher habe ich sie unverändert gelassen.

  • love.draw()ist die Zeichenfunktion von LÖVE und hat einen vorgegebenen Namen. Alternative LÖVE-Funktionen, die verwendet werden könnten, wären love.update(dt)undlove.run() - die erste ist länger, in Bytes, und die letztere ist kürzer, ja, aber ohne eine eingebaute Endlosschleife. Daher draw()scheint hier unsere beste Wahl zu sein.

  • In der obigen Version wird love.graphics.pointsder Ball gezogen. Obwohl kürzer, bin ich mir nicht sicher, ob es erlaubt ist. Hier ist ein GIF, wie es läuft:

Animierter Screenshot - Punkt

Wie Sie sehen können (oder vielleicht auch nicht können), bewegt sich ein einzelnes Pixel auf dem Bildschirm. Das spart zwar Bytes, ist aber nicht das befriedigendste Ergebnis.

Also habe ich eine alternative 131-Byte-Lösung erstellt :

x,y,a,b=0,0,1,1
function love.draw()a=(x<0 or x>795)and-a or a
b=(y<0 or y>595)and-b or b
x=x+a
y=y+b
love.graphics.print(0,x,y)end

Dieser verwendet love.graphics.print- was Text druckt - und a 0als Kugel, wodurch es viel sichtbarer und ansprechender wird.

Animierter Screenshot - Null

Matheus Avellar
quelle
1

CHIP-8, 36 34 28 Bytes

FF29 'LDF I,vF //load digit sprite for the value of vF (should be 0)

4000 'SNE v0,0 //if x is 0...
6201 'LD v2,1 //set x velocity to 1
403C 'SNE v0,3C //if x is 3C...
62FF 'LD v2,FF //set x velocity to -1
4100 'SNE v1,0 //if y is 0...
6301 'LD v3,1 //set y velocity to 1
411B 'SNE v1,1B //if y is 1B...
63FF 'LD v3,FF //set y velocity to -1

D015 'DRW v0,v1,5 //draw sprite
D015 'DRW v0,v1,5 //draw sprite again to clear it.
8024 'ADD v0,v2 //add x velocity to x
8134 'ADD v1,v3 //add y velocity to y

1202 'JMP 202 //jump to second instruction

Keine ausgefallenen Tricks hier ...

Benötigt einen Interpreter, der Sprites korrekt zeichnet (es kann nur ein Sprite pro Frame gezeichnet werden, wodurch das Programm so verlangsamt wird, dass Sie es sehen können).

Video von geringer Qualität

12Me21
quelle
0

ZX Spectrum BASIC - 179 Bytes

Hier ist es nur ein bisschen verdichtet. Es ist 179 Bytes mit der eingeschlossenen Kugelgraphik

  10 LET a=10: LET b=10: LET c=1: LET d=-1: FOR e=0 TO 7: READ f: POKE USR "a"+e, f: NEXT e
  20 DATA 60, 126,243,251,255,255,126,60
  30 PRINT AT b,a;"\a"
  40 IF a<1 OR a>30 THEN LET c=-c
  50 IF b<1 OR b>20 THEN LET d=-d
  60 LET a=a+c: LET b=b+d: PRINT AT b-d, a-c;" ": GO TO 30
DrIB
quelle
Sehen Sie sich die Kennzeichnung für die Antworten an, indem Sie auch das Zeichen verwenden, ooder OSie können möglicherweise einige Bytes in der symbolischen Liste speichern. Sie können auch frühere Antworten bearbeiten, wenn Sie Lösungen verbessert haben, anstatt dieselbe Frage erneut zu beantworten
Shaun Bebbers,