8-bitowa odbijająca się piłka wokół płótna


20

Zainspirowany tą ofertą z Przewodnika użytkownika Commodore 64:

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

Utwórz podobny program w wybranym języku / platformie, aby odbić obiekt podobny do kuli wokół terminala, ekranu, kanwy lub innego obszaru wyświetlania wizualnego.

Nie musisz dokładnie naśladować grafiki PETSCII z C64, proste Olub ozrobi to, ani nie musisz używać GOTOpolecenia, jeśli nadal istnieje ono w twoim języku. Tak długo, jak twoja piłka zaczyna się na górze płótna i porusza się po przekątnej, aż osiągnie limit płótna, a następnie odpowiednio się odbija, w następujący sposób:

  • Podróż w dół i w prawo i uderzanie w dolną część ekranu, odbija się i kontynuuje w prawo;
  • Podróżowanie w górę i w prawo, uderza w skrajną prawą granicę i odbija się w lewo iw górę;
  • Podróżując w lewo i w górę i uderzając w górę, odbija się w lewo iw dół;
  • Podróżując w lewo i w dół i osiągając skrajną lewą granicę, odbija się w prawo i w dół;
  • Uderza w każdy kąt i zmienia kierunek;

Więc wszyscy jesteśmy dobrzy.

Nie musisz też przesuwać piłki 8 pikseli, tak jak dzieje się to na liście BASIC na C64; możesz przesuwać jeden blok znaków lub piksel na raz, w zależności od tego, co uważasz za najbardziej odpowiednie.

Aby zobaczyć działanie tej listy BASIC, możesz wpisać ją za pomocą tego internetowego emulatora Commodore 64, pod warunkiem, że Twoja przeglądarka obsługuje Flash.


2
Płótno JavaScript. .ه.
Matthew Roh

Nie jestem pewien, jak dziś nazywasz ekran. Kiedyś oglądałeś tylko ekran i obramowanie przez telewizor lub VDU ... a teraz masz terminale, okna, płótna, standardowe wyjście itp. ... to wszystko jest dla mnie bardzo mylące.
Shaun Bebbers

Byłoby lepiej, gdybyśmy mieli stałą wartość wielkości pikseli.
Matthew Roh

4
Czy możemy założyć rozmiar ekranu 1x1 i drukować na zawsze?
Matthew Roh,

1
możliwy duplikat ASCII Ball in Box Animation
Titus

Odpowiedzi:


3

Kod maszynowy 6502 (C64), 90 89 91 bajtów

+2 bajty, ponieważ potrzebuje adresu ładowania (nie PIC z powodu własnej modyfikacji)

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

Demo online

Stosowanie: sys49152

Starałem się zmniejszyć rozmiar (np. NIE używam IRQ do pomiaru czasu, ale zamiast tego głupie puste pętle), nadal nie jestem w stanie osiągnąć poziomu gry C64 BASIC w grę Titusa : o, cóż. Ale wygląda mniej migotać;)

Objaśnienie: (demontaż imadeł)

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

Dla zabawy, oto bardziej profesjonalny wariant wykorzystujący duszka do piłki i flashujący ramkę po trafieniu w 385 bajtów (zawierający dane duszka, które są używane w miejscu ):

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 

Demo online - | - przeglądaj źródło asemblera ca65

Rozpocznij i zatrzymaj odbijającą się piłkę za pomocą sys49152.

  • To powoduje, że C64 BASIC działa, a dokonuje się to poprzez przesunięcie przestrzeni adresowej VIC-II do góry $C000, co wymaga skopiowania zawartości ekranu i zestawu znaków (czcionek).
  • Łączy się z IRQ systemu i aby uniknąć migotania, zmienia źródło tego IRQ na układ graficzny VIC-II, więc aktualizacje są zawsze wykonywane między ramkami.
  • Usterki:
    1. RUN/STOP + RESTORE jest zepsuty, nie próbuj.
    2. Przy VIC-II jako źródle IRQ kursor miga nieco wolniej i TI$również pozostaje w tyle.
    3. gdy zatrzymasz się, gdy ramka jest flashowana (bardzo mało prawdopodobne, ale możliwe), pozostaje biała - musisz przywrócić ją ręcznie.

1
To nie jest całkowicie niezależne, prawda? Widzę dwa absolutne LDA i dwa STA. Niemniej jednak świetna robota!
Tytus

Cholera, masz rację: o Zapomniałem modyfikacji siebie! Zaktualizuję jak tylko będę na komputerze.
Felix Palmen

1
@Titus naprawiono ... i dla zabawy dodano „lepszy” wariant :)
Felix Palmen,

Czy zastanawiałeś się nad zapakowaniem duszka? (Hmm ... użyć zestawu znaków ROM?) I wolałbym więcejinc $d020 niż jsr flash;) hithimselfwithalargetrout To jest cudowne!
Tytus

1
@Titus zapisałby 2 bajty, tak. Jeśli chodzi o adres ładowania, jest to część prawidłowego .prgpliku i z mojego meta pytania tutaj biorę, że muszę go dołączyć ... prawdopodobnie mógłbym go pominąć, gdyby kod był niezależny od pozycji.
Felix Palmen,

14

Narzędzia Bash + Unix, 125 117 bajtów

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
}

Animacja przykładowego przebiegu:

Animation of sample run


6
Uderzył dokładnie w róg! : O
mbomb007

11

Zespół CP-1610 , 6764 62 DECLE = 78 bajtów

Ten kod jest przeznaczony do uruchamiania na Intellivision . Używa jednego ze swoich spriteów sprzętowych, znanego jako MOB (dla obiektu mobilnego).

Kod operacji CP-1610 jest kodowany za pomocą 10-bitowej wartości, zwanej „DECLE”. Ten program ma 62 DECLE długości, zaczynając od 4800 $, a kończąc na 483D.

Zrzut szesnastkowy + źródło

                            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

Wynik

output


10

HTML (Microsoft Edge / Internet Explorer), 81 bajtów

Udawaj, że jest 1998 z tymi zagnieżdżonymi <marquee>znacznikami:

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

Testowany w Microsoft Edge, choć z tego, co przeczytałem, IE powinien nadal obsługiwać markizy. Zdecydowanie nie działa w Chrome.

Ustawienie direction=uppozwoliłoby zaoszczędzić 2 bajty, ale łamie zasadę, że piłka musi zaczynać się na górze płótna.


Niestety, jest to nieprawidłowa odpowiedź, ponieważ piłka nie porusza się po przekątnej, jak wymaga tego wyzwanie.
El'endia Starman

Próbowałeś go w Microsoft Edge? Chrome nie obsługuje tego directionatrybutu.
Jack Brounstein,

Przepraszam - działa w Edge. Mogę potwierdzić, że nie działa w Chrome i mogę zaświadczyć, że działa w Firefox i Internet Explorer. Trzy na cztery nie są złe (i potrzebujesz tylko jednej, aby ta odpowiedź była poprawna). +1
El'endia Starman

1
+1 za marquee, to całkiem kreatywne!
Metoniem

Pracowałem dla mnie w Chrome.
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

Dosłownie dosłowne tłumaczenie, nie zdziwiłbym się, gdyby istniały sztuczki, aby je zmniejszyć.

Ekran ma wymiary 16 x 8 i indeks 1, więc stałe są różne.

~ jest sposobem SourceCodera na zapisanie symbolu negacji.

gif odbicia O

Wygląda płynniej na sprzęcie.


Czy jesteś pewien, że to 70 bajtów? Wygląda na mniej niż to.
maja 21

@ 12Me21 ile bajtów się liczy? Dostaję 80 bajtów, jeśli zachowam to na kalkulatorze, i 10 bajtów na pusty program, który zgadza się z moją liczbą.
Harold,

Och, chyba wtedy pomyliłem się.
maja 21

7

Befunge, 209 bajtów

>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_^

Zakłada się, że ekran ma rozmiar 80 x 25, ale można łatwo dostosować zakres, zastępując "O"(79) w ostatnim wierszu i *64(24) w drugim ostatnim wierszu (zwróć uwagę, że drugi ostatni wiersz jest wykonywany od prawej do lewej). Prędkość można również regulować, zastępując "2"(50) na ostatniej linii.


7

Java, 184 176 bajtów

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);}}

Wykorzystuje to sekwencje specjalne ANSI do przeniesienia kursora, który jest obiektem odbijającym się wokół 85 x 25wyświetlacza terminala. Zapisz w pliku o nazwie A.java.

Nie golfił

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;
        }
    }
}

Próbny

Przykład


To jest kod golfowy, więc będziesz chciał go usunąć Thread.sleep(50). A twoje programy w golfa i nie w golfa się nie zgadzają.
Jakob

4

Clojure, 398 380 375 bajtów

(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 bajtów, zmieniając nazwę czcionki na pusty ciąg znaków, aby domyślnie, wstawiając kontrole granic i rozwiązując problem dolnej granicy (który można zobaczyć w pliku GIF). Naprawianie faktycznie zapisanych bajtów.

-5 bajtów, zmieniając na bardziej zwięzłą składnię destrukcyjną i zmniejszając piłkę o piksel.

Używa Quil .

Próbowałem przejść do trybu funkcjonalnego, ale wymagało to dużo dodatkowego kodu i ostatecznie było droższe.

(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 Bouncing GIF

(Uwaga: nowa wersja nie odbija się wcześnie u dołu ekranu, tak jak w przypadku GIF-a).


Właśnie zdałem sobie sprawę, że (+ 0 font-size)tam mam . To jest żenujące. Naprawię to w następnej wersji. Powinieneś oszczędzić mi 5 bajtów.
Carcigenicate

4

Rakieta 247 bajtów

(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))

Nie golfowany:

(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)

Wynik:

wprowadź opis zdjęcia tutaj


1
Granie w racquetball z rakietą!
ckjbgames

To jest dobre!
rnso

„Rakieta” pochodzi z języka programowania „Scheme”: po Scheme (przebiegły plan) pojawia się Racket (oszustwo lub oszustwo)!
rnso

@mso Jeszcze lepiej!
ckjbgames

3

Galaretka, 37 bajtów

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

Z pewną pomocą od tej odpowiedzi na temat prawidłowego wykonania pętli i znaków ucieczki. Obecnie odbija się na ekranie 80x24, ale można to łatwo zmodyfikować w kodzie.

Współrzędne w każdym kierunku może być reprezentowana jako elementy dwóch list [0, 1,..., 24, 23,..., 1]i [0, 1,..., 80, 79,..., 1], nazwijmy je Yi X, które są powtarzane w nieskończoność. To nieskończone powtarzanie można emulować za pomocą indeksowania modułowego - w Galaretce. Przykład: podczas iiteracji piłka jest w pozycji (X[i%|X|], Y[i%|Y|]) = (iịY, iịX). Ruchoma kula jest tylko kursorem, który jest ustawiany w pozycji, emitując iịYznaki nowej linii i iịXspacje.

Próbny

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

Wyjaśnienie

“ñ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.

2

SmileBASIC, 85 74 bajtów

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

Położenie piłki można modelować za pomocą 2 fal trójkątów, a najkrótszym sposobem, w jaki udało mi się je wytworzyć w SmileBASIC, było arcsine (sine (x)). (algorytm używający MOD był dłuższy, ponieważ SB używa MODzamiast niego %)


2

CSS / HTML, 200 + 7 = 207 bajtów

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

Ta wersja pokazuje rozmiar płótna, a także nadaje animacji bardziej piksele:


2

Dyalog APL, 44 bajty

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

Wyjaśnienie:

  • {... }⍨1 1: wywołaj daną funkcję za pomocą ⍺ = ⍵ = 1 1
    • ⎕SM∘←0,G←⍺+⍵: Przechowywać ⍺+⍵w G, wyświetlał 0się w tym miejscu w ⎕SMoknie.
    • ⎕DL.1: poczekaj 1/10 sekundy
    • ⊃1 G∨.≥G⎕SD: Sprawdzenie, czy Gznajduje się w ⎕SMgranicach okna ( 1≥Glub G≥⎕SD, ⎕SDto y creen d imensions)
    • 1-2×: mapa [1,0]na [¯1,1], aby zmienić kierunek podróży
    • ⍵×: pomnóż przez to bieżący kierunek jazdy
    • G∇: rekurencja, niech Gbędzie nowa lokalizacja ( ) i ⍵....będzie nowym kierunkiem ( ).

Czy to ma ciągle otwierać i zamykać terminale podczas pracy? Trudno jest zatrzymać to uruchamianie po uruchomieniu, ponieważ terminal zamyka się i otwiera co dziesiąte sekundy (przynajmniej w systemie Windows).
ren

1
@wptreanor: naprawiono
marinus

super, świetna robota!
ren

2

PHP, 112 97 94 103 102 bajtów

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));

odbija kapitał Ona siatce 40 x 25, zaczynając od prawego górnego rogu;
drukuje 99 nowych linii, aby wyczyścić ekran.

Uruchom z -nr.

A^K= chr(10)= nowa linia
A^a= chr(32)= spacja


1
Cześć Tytus, to znowu ja. 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);. Modulo ma wartość false przy 0 i N i odwraca kierunek. Niestety musimy zainicjować $ d i $ e do -1, ale nadal możemy uzyskać oszczędności. $x%79<=>.5działa również dla tych samych bajtów.
Christoph

1
Cześć @Christoph witamy ponownie. Dziwne: kiedy skopiowałem Twoje rzeczy, miał 116 bajtów zamiast 110. Ale zainspirowało mnie do czegoś znacznie krótszego.
Tytus

Jesteśmy zdecydowanie dobrym zespołem;) Dziwna rzecz przy kopiowaniu Nie mam pojęcia, dlaczego.
Christoph

2

Simons´ BASIC (C64), 66 65 bajtów

Jeden bajt zapisany dzięki @ShaunBebbers.

Potrzebuję tylko jednej linii, ponieważ Simons´ Basic ma funkcję modulo.
Po tym, wymaga to fizycznego C64 i modułu Simona BASIC
(lub dowolnego innego rozszerzenia BASIC, które ma modfunkcję).

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

Wpisz 69 znaków:

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

{CLR}to PETSCII 147, który czyści ekran. Użyj Shift + CLR / HOME, aby wpisać.

bytecount

Kiedy zapisany na dysku, to zajmuje 65 bajtów, ponieważ polecenia są tokenized:
for, to, poke, abs, nexti gototo jeden bajt każda; modzajmuje dwa bajty.
To daje 59 bajtów kodu plus 4 bajty na wskaźniki i 2 bajty na numer linii.

W celach informacyjnych patrz Mapowanie C64 i wyszukiwanie $800(Tekst programu w języku BASIC).
(Obszar pamięci ekranu wideo można znaleźć pod adresem$400 .)

awaria

Program zapętla Iod 0 do 623 (= LCM 48 i 78 minus 1). W pętli

  • ekran jest wyczyszczony
  • I zostanie zmapowany do 39..0..38 odpowiednio 24..0..23
  • i obiekt blob (PETSCII 81) zostaje umieszczony w odpowiedniej pozycji w pamięci wideo
    (tak jak robi to oryginalny program).

Po zakończeniu pętli program jest ponownie uruchamiany przez przejście do linii 0.

C64 BASIC, 77 76 bajtów

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

Niestety potrzebuję dwóch linii, ponieważ nawet przy wszystkich możliwych skrótach zajęłoby to 83 znaki - zbyt wiele, aby użyć edytora linii C64:

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

(Można użyć edytora szesnastkowego, aby utworzyć dłuższą linię - co dałoby 73 bajty.)


1
Separatory poleceń Commodore są :i nie;
Shaun Bebbers

1
Również jeśli zaczynasz od linii zerowej, możesz po prostu użyć gotow wersji gotogoto 0
dwuliniowej

Jeśli chcesz uzyskać więcej poleceń na liście C64 BASIC, wprowadź go do C128 w trybie 128, zapisz go na dysku i załaduj z powrotem do trybu C64, C128 ma domyślnie limit 160 znaków, aby tę barierę można przełamać używając skrótów słów kluczowych Commodore.
Shaun Bebbers

@ShaunBebbers miło wiedzieć. To było tak długo. Chciałem również zaimplementować to w kodzie maszynowym ... próbując podsumować procedury jądra; nie jestem pewien, kiedy muszę wykonać kopię zapasową rejestrów; pełna lista jądra jest w trybie online ; Po prostu nie mogę znaleźć czasu na dalsze kopanie. Chcesz, aby zakończyć ten ?
Tytus

Zamierzałem stworzyć wersję MC, choć myślę, że poddanie jej własnemu wyzwaniu byłoby dla mnie zbyt pobłażliwe. Najszybszym sposobem byłoby zapisanie bajtu bezpośrednio na ekranie od $0400do $07e7; lub użyj duszka. Używanie Kernala z $ffd2(akumulatorem wyjściowym) działałoby, ponieważ dość łatwo można ustawić pozycję X i Y na kursorze (nie pamiętam wezwania do tego), ale może być konieczne uniknięcie pozycji ostatniego znaku na wypadek, gdyby wymusił kanał informacyjny.
Shaun Bebbers

1

Python 2, 176 168 bajtów

Zakłada się, że rozmiar terminala wynosi 80 x 24. Zdecydowanie nie optymalne, ale jestem nowy w golfa, więc tak.

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)

Dzięki R. Kap za sugestię x% 79 <1 zamiast x <1 lub x> 79 i to samo dla y.


Można zaoszczędzić kilka bajtów zastępując x<1or x>78z x%79<0i y<1or y>22z y%23<1.
R. Kap

1

Rebol / View, 284 266 bajtów

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]]]]

Nie golfowany:

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
            ]
        ]
    ]
]

1

C 294 bajtów

#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);}}

Wersja bez golfa:

#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);

  }   

}

Wyjaśnienie

  • Aby zacząć, musiałem dostać się graphics.hdo mojego /usr/includekatalogu. Dlatego szukałem i to właśnie znalazłem. Jest to implementacja TurboC Graphics wykorzystująca SDL dla systemu Linux. Można również użyć OpenGL. Wydaje mi się, że w Windows jest już zainstalowany, nie jestem pewien co do MacOS.
  • void initgraph(int *graphdriver, int *graphmode, char *pathtodriver);inicjuje system i przełącza go w tryb graficzny, w tym przypadku sterownik karty graficznej jest wykrywany automatycznie. Więcej informacji można znaleźć pod tym linkiem .
  • xi ysą współrzędnymi, które określają pozycję piłki.
  • ai bsą flagami, ajest ustawiany na zero, gdy xwartość spada poniżej 60 i bjest ustawiany na zero, gdyy spada poniżej 60.
  • Flagi są przełączane, gdy xiy przekracza wartości graniczne z oknem, i współrzędne są odpowiednio dostosowane.
  • Położyłem usleeptak, aby mój procesor się nie stresował.
  • Zwykle należy użyć closegraph()połączenia, aby zamknąć okno. Ale tutaj go brakuje.

Musi zostać skompilowany z flagą linkera -lgraph

Działa płynniej na prawdziwym sprzęcie. :)

Odbijając czerwoną piłkę


Czy instrukcje importu są niezbędne do uruchomienia tego programu?
Kritixi Lithos

@KritixiLithos Tak, proszę pana; Zaktualizowano! musisz dołączyć graphics.h. Ta odpowiedź askubuntu.com/questions/525051/… była pomocna.
Abel Tom

1

MATL , 42 bajty

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

Wykorzystuje ekran i postać 70 × 16 O. Jeśli zaczekasz na kilka odbić, zobaczysz, jak piłka uderza w róg.

Wypróbuj w MATL Online!

Rozmiar ekranu można łatwo modyfikować w kodzie. Odpowiednią częścią jest to 8E70, która popycha 8, podwaja ją i popycha 70. Na przykład, dla ekranu o wymiarach 80 × 25 zamień na 5W80, który popycha 5, obciosuje i popycha80 (lub zamień na25 80 , ale wymaga jeszcze jednego bajtu).

Ponadto dodanie tDna końcu kodu pokazuje bieżącą pozycję w czasie rzeczywistym (pionowy, a następnie poziomy, 1 1to lewy górny róg). Na przykład dla 80×18ekranu

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

Wypróbuj też!

Wyjaśnienie

Używa nieskończonej pętli. Pozycja jest przechowywana w schowku Hjako wektor 1 × 2, a kierunek jest przechowywany w schowku Ijako wektor 1 × 2 z wpisami 1lub-1 .

Każda iteracja czyści ekran, określa macierz odstępów, zapisuje O odpowiednią pozycję i wyświetla ją. Następnie należy zaktualizować pozycję i kierunek.

Pozycja jest 1oparta, a zatem są krawędzie ekranu 1i maksymalny rozmiar ekranu. Więc jeśli rozmiar ekranu modulo pozycji daje 0lub 1w pierwszym lub drugim składniku, co oznacza, że ​​osiągnęliśmy odpowiednio pionową lub poziomą krawędź, to ten składnik wektora kierunku jest negowany. Następnie nowy kierunek jest dodawany do bieżącej pozycji w celu uzyskania nowej pozycji.


1

Oto lista 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

Miły pierwszy wpis DrlB - czy możesz podać liczbę bajtów. Zakładam, że to zadziała na dowolnej Speccy, w tym na maszynach 16K?
Shaun Bebbers

Cześć, to 201 bajtów, możesz pominąć pierwsze 4 wiersze, ale wtedy otrzymujesz tylko odbijający się znak „a”, ale oszczędza to 64 bajty. Spróbuję zoptymalizować. To nic szczególnego i będzie działać na każdym modelu Spectrum :)
DrIB

Ok, udało mi się zmniejszyć go do 185, trochę zagęszczając linie bez upuszczania grafiki. Jest to jednak nieco mniej czytelne, ale jest szybsze.
DrIB

1

Klątwy C +, 190 bajtów

#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();}}

Wyjaśnienie:

#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();
    }
}

1

Lua ( LÖVE 2D ), 130 bajtów

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 nie jest najlepszym językiem, jeśli chodzi o golfa kodowego, ale proszę bardzo! Kilka punktów, o których warto wspomnieć:

  • Domyślny rozmiar płótna to 800 x 600. Można go zmienić w pliku konfiguracyjnym, ale nie widziałem żadnych ograniczeń rozmiaru, więc zostawiłem go bez zmian.

  • love.draw()jest funkcją rysunkową LÖVE i ma z góry określoną nazwę. Alternatywnymi funkcjami LÖVE, które mogłyby być użyte, byłyby love.update(dt)i love.run()- pierwsza jest dłuższa, w bajtach, a druga krótsza, tak, ale bez wbudowanej nieskończonej pętli. draw()Wydaje się więc, że jest to nasz najlepszy zakład tutaj.

  • Powyższa wersja służy love.graphics.pointsdo rysowania piłki. Chociaż krótszy, nie jestem pewien, czy jest to dozwolone. Oto GIF jego działania:

Animowany zrzut ekranu - punkt

Jak widać (a może nie), na ekranie porusza się pojedynczy piksel. To oszczędza bajty, ale nie jest to najbardziej satysfakcjonujący wynik.

Więc stworzyłem alternatywne rozwiązanie 131 bajtów :

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

Ten używa love.graphics.print- który drukuje tekst - i 0jako piłkę, dzięki czemu jest znacznie bardziej widoczny i atrakcyjny.

Animowany zrzut ekranu - zero


1

CHIP-8, 36 34 28 bajtów

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

Żadnych wymyślnych sztuczek tutaj ...

Wymaga interpretera, który poprawnie rysuje ikonki (na ramkę można narysować tylko jednego ikonkę, co spowalnia program na tyle, abyś mógł go zobaczyć).

Niska jakość wideo


0

ZX Spectrum BASIC - 179 bajtów

Tutaj jest tylko trochę skondensowane. Ma 179 bajtów z dołączoną grafiką

  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

Proszę spojrzeć na narzut wykorzystany do odpowiedzi, również za pomocą znaku olub Omożesz zapisać niektóre bajty na liście symbolicznej; możesz również edytować poprzednie odpowiedzi, gdy
ulepszysz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.