Прото-космические захватчики (можете это сделать?)

18

Прото космические захватчики

Это задача графического вывода, где задача состоит в том, чтобы дать самый короткий код для каждого языка.

задача

Ваш код должен позволять пользователю перемещать следующего иностранца по экрану / окну.

введите описание изображения здесь

Ваш код может просто загрузить его из локального файла. Не стесняйтесь преобразовать его в другой стандартный формат изображения или даже исправить небольшие пиксельные ошибки в изображении, которые были указаны в комментариях.

Фон должен быть белым, а окно / экран должно быть не менее 400 на 400 пикселей. Если ваш язык не поддерживает такие большие окна / экраны, используйте самый большой размер, который он поддерживает, если он не меньше 200 на 200.

Для перемещения иностранца по экрану код должен поддерживать вверх / вниз / влево / вправо с помощью клавиш со стрелками на стандартной клавиатуре.

Ваш код должен быть полной программой .

Ограничения / ограничения

Инопланетянин должен остановиться на границах. Он также должен плавно двигаться с одинаковой скоростью, без видимого мерцания или заикания, и должен отображаться со скоростью не менее 24 кадров в секунду. Переход от одной стороны экрана / окна к другой должен занимать от 2 до 5 секунд.

Языки и библиотеки

Вы можете использовать любой язык или библиотеку, которая вам нравится (которая не была разработана для этой задачи). Тем не менее, я хотел бы иметь возможность протестировать ваш код, если это возможно, поэтому, если вы можете предоставить четкие инструкции по его запуску в Ubuntu, это было бы очень полезно.

Каталог

Фрагмент стека в нижней части этого поста создает каталог из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

## Language Name, N bytes

где Nразмер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Если вы хотите включить в заголовок несколько чисел (например, потому что ваш результат равен сумме двух файлов или вы хотите перечислить штрафы за флаг интерпретатора отдельно), убедитесь, что фактический результат является последним числом в заголовке:

## Perl, 43 + 2 (-p flag) = 45 bytes

Вы также можете сделать имя языка ссылкой, которая будет отображаться во фрагменте кода:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


источник
2
Можем ли мы построить пришельца сами? Если так, нужно ли нам включать пиксельные ошибки (я полагаю?) Из картинки?
mnxomaτ
@ mınxomaτ Это не ограничивается Linux! Обратите внимание, «если это возможно».
@nimi Спасибо. Добавлено, что вы можете загрузить его из локального файла.
@ mınxomaτ Вы можете создать его самостоятельно или просто загрузить из локального файла. Я не заметил ошибок в пикселях, но я предполагаю, что при загрузке в любом случае будет меньше кода.
Можете ли вы определить «остановка на границах»? Должен ли весь инопланетянин быть постоянно видимым или он может частично остановиться за пределами границы?
Тимотимх

Ответы:

12

Царапина , 221 217 байт

Нажмите на изображение, чтобы увидеть его в действии. Движение определяется нажатиями клавиш , поэтому оно будет более плавным, чем быстрее будет установлено повторение нажатия клавиш .

Изображение включено в проект, но байты Царапины обычно считаются из текстового представления в гольфе , согласно этому мета-посту . Если есть разногласия относительно того, является ли это приемлемым (или достаточно ли плавное движение), дайте мне знать, и я постараюсь обойти это.

timothymh
источник
Этот ответ очень весело!
Как вы измерили размер этой программы?
@Lembik см. Второй абзац.
Тимотимх
1
генерирует в 217 байтов: scratchblocks.github.io/…
ev3commander
1
@Mauris Да, об этом позаботится команда «если на грани, отскок». Вы можете играть в демо, нажав на изображение!
Тимотимх
7

Обработка 2, 219 199 241 220 219 байт

int a,x=0,y=0;void setup(){size(500,500);}void draw(){background(-1);image(loadImage(".png"),x,y);if(keyPressed){a=keyCode;if(a==38)y--;if(a==37)x--;if(a==40)y++;if(a==39)x++;}x=constrain(x,0,436);y=constrain(y,0,454);}

Требуется изображение, сохраненное .pngв том же каталоге, что и .pde

Доктор
источник
6

Python 2, 262 253 246 240 байт

from pygame import*
init()
key.set_repeat(1)
p=[0,0]
d=display
c=d.set_mode((400,)*2)
while c.fill((255,)*3):
 e=event.get(2);c.blit(image.load("I"),p);d.flip()
 if e:x=e[0].key+1;q=x&2;b=q/2;p[b]=max(0,min(336+b*16,p[b]+(1-q)*(1-(2*x&2))))

Вау. Как много хакерства.

Использует модуль 'pygame', найденный на http://pygame.org .

объяснение

key.set_repeat(1) - Отправлять повторяющиеся ключевые события через систему событий каждую миллисекунду

c=d.set_mode((400,)*2) - Создайте поверхность дисплея 400x400

while c.fill((255,)*3):- Эффективно, while 1:но также очищает экран

e=event.get(2);c.blit(image.load("I"),p);d.flip()- Собирайте только события клавиатуры, загружайте изображение из png-файла Iи рисуйте его. Обновить экран

if e:x=e[0].key+1;q=x&2;b=q/2;p[b]=max(0,min(336+b*16,p[b]+(1-q)*(1-(2*x&2)))) - Если произошло событие, определите, какая клавиша со стрелкой была нажата (странные вещи, если вы нажимаете другие клавиши), а затем измените положение поверхности в зависимости от того, какую клавишу вы нажали.

синий
источник
Мне очень нравится ваше решение.
@Lembik То есть разрешено использовать одно байтовое имя файла? (Т.е. без расширения?). Если это так, я предлагаю полностью исключить имена файлов из числа байтов.
Mynxomaτ
@ mınxomaτ Мне разрешено использовать однобайтовое имя файла, но я не хочу придумывать новую схему подсчета очков.
@Lembik Processing не может обрабатывать однобайтовые имена файлов ... так что это несправедливо.
Доктор
2
@TheDoctor Это только на: разные языки разные! Я полагаю, что мы также запрещаем вызовы, которые принимают ввод от stdin, потому что несправедливо, что в Python для этого требуется так много символов ...
Алекси Торхамо,
5

Haskell, 410 байт

import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game
main=do b<-loadBMP"b";play(InWindow""(400,400)(0,0))white 200((0,0),id)(b#)e(%)
e(EventKey(SpecialKey k)Down _ _)(c,_)|k==KeyUp=(c,fmap(+1))|k==KeyDown=(c,fmap(+(-1)))|k==KeyLeft=(c,((+(-1))?))|k==KeyRight=(c,((+1)?))
e(EventKey _ Up _ _)(c,_)=(c,id)
e _ w=w
_%(c,f)=(s?(s<$>f c),f)
s=min 200.max(-200)
b#((x,y),_)=Translate x y b
f?(a,b)=(f a,b)

Изображение иностранца ожидается в файле с именем bв .bmpформате.

Я новичок в библиотеке Gloss, так что, возможно, это не оптимально. Кто-нибудь знает, могу ли я проверить, нажата ли клавиша вместо отслеживания KeyUp/ KeyDownсобытий?

Как это работает: последними четырьмя параметрами playявляются состояние мира (инициализируется с ((0,0),id)помощью, функция для рисования изображения из состояния ( #), обработчик события ( e) и функция, которая изменяет состояние с течением времени ( %).

Состояние представляет собой пару координат xy и функцию их изменения при каждом %вызове.

#перемещает растровое изображение ( b) к текущим координатам и рисует его.

eищет либо KeyDownсобытия клавиш курсора и устанавливает соответствующие функции в состоянии, либо для KeyUpлюбой клавиши для сброса функции в состоянии на функцию идентичности.

% применяет функцию из состояния к текущим координатам и проверяет границы.

Ними
источник
Я всегда удивляюсь, что вы можете делать такие вещи в Хаскеле. Спасибо!
4

Вяз, 240 байт

import Graphics.Element as G
import Keyboard as K
import Time
import Signal exposing(..)
c=min 800>>max 64
i(x,y)=G.container x y G.middle(G.image 64 48"http://i.stack.imgur.com/CUweU.png")
main=i<~foldp(\{x,y}(v,w)->(c v+x,c w-y))(99,99)(sampleOn(Time.fps 200)K.arrows)

Попробуй это здесь . Количество байтов указывается после замены URL на .png.

Линн
источник
Возможно, мне придется выучить вяз сейчас. Спасибо.
3

AutoIt , 269 267 байт

#include<Misc.au3>
GUICreate(0,-1,-1,-1,-1,-1,34078728)
$0=GUICtrlCreatePic("b.bmp",0,0,64,48)
GUISetState()
Dim $1,$2
$3=_IsPressed
Do
$1+=$3("27")-$3("25")
$2+=$3("28")-$3("26")
$1=($1>336)?336:($1<0)?0:$1
$2=($2>352)?352:($2<0)?0:$2
GUICtrlSetPos($0,$1,$2)
Until 0

Требует, чтобы изображение было сохранено как b.bmp в каталоге скриптов. Если вы хотите использовать изображение с реальной прозрачностью, вам нужно преобразовать его из PNG в 32-битное растровое изображение (OT: действительно недооцененный формат).

объяснение

Нам нужно импортировать, Misc.au3чтобы получить доступ к _IsPressed. Функция, которая принимает код клавиши и возвращает Trueили Falseкогда клавиша нажата.

Спецификация задачи довольно крутая в том смысле, что нам нужно создать квадратное окно размером 400 пикселей. Параметры размера по умолчанию (обозначены как -1или Default) 400x400. Расширенный стиль окна устанавливается в 34078728. Это заставляет окно быть двойной буферизацией и рисуется снизу вверх. Это необходимо для устранения мерцания в соответствии с требованием вызова. В Windows 10 эта необычная (и несколько недокументированная) комбинация стилей нарушает заголовок окна (все эффекты зависания отключены).

$1и $2объявлены и будут содержать смещение x и y изображения, загруженного элементом управления $0. $3становится указателем на функцию, _IsPressedчтобы значительно сократить код.

Поскольку нет необходимости иметь возможность выхода из программы, этот скрипт выполняется в бесконечном цикле ( Until 0).

$1+=$3("27")-$3("25")нарушает тип данных в AutoIt, динамически приводя логическое значение, возвращаемое из _IsPressedцелого числа, которое может быть добавлено или добавлено из смещения x. То же самое для вас. $1=($1>336)?336:($1<0)?0:$1использует троичный оператор, известный из C-подобных языков, чтобы выполнить проверку границ, чтобы остановить иностранца на границах.

GuiCtrlSetPos перемещает элемент управления изображением на новые координаты.

Вот скриншот с прозрачным инопланетянином (вы можете даже перемещаться по диагонали):

Скриншот

mınxomaτ
источник
Ваш фон не белый!
sergiol
2

Lua + LÖVE, 291 персонажа

x=0
y=0
l=love
g=l.graphics
l.window.setMode(400,400)
i=g.newImage("i")
function l.update()d=l.keyboard.isDown
if d("left")and x>0 then x=x-1 end
if d("right")and x<336 then x=x+1 end
if d("up")and y>0 then y=y-1 end
if d("down")and y<352 then y=y+1 end
end
function l.draw()g.draw(i,x,y)end

Это использует неизменяемое окно 400 x 400. У меня не было успеха в настройке love.keyboard.setKeyRepeat()для ускорения чтения ключа, поэтому я сделал рекомендуемый способ, опросив состояние каждой клавиши.

Поскольку мои отношения с Lua forне самые лучшие, на этот раз не удалось сделать цикл короче, чем жесткое кодирование дампа состояния каждого ключа.

manatwork
источник
2

SpecBAS - 285 255 байт

1 GRAPHIC NEW v LOAD "inv8.bmp" TRANSPARENT 15
2 PALETTE COPY v,0,1 TO 5: GRAPHIC REMAP v
3 LET x,y=100
4 CLS : WINDOW PUT GRAPHIC v,0,x,y
5 LET x=x+KEYST(39)-KEYST(37),y=y+KEYST(40)-KEYST(38)
6 LET x=CLAMP(x,1 TO 400),y=CLAMP(y,1 TO 400)
7 WAIT SCREEN 
8 GO TO 4

Загружает изображение - цвет 15 ярко-белый, поэтому он становится прозрачным.

Использование исходного изображения и палитры SpecBAS по умолчанию сделало его немного странным, поэтому строка 2 переключает их в соответствии с входным изображением. На рисунке ниже показано, как это выглядит без строки 2 и после.

введите описание изображения здесь

Команда CLAMP ограничивает изображение от 1 до 400 в обоих направлениях, экономит на нескольких операторах IF ... THEN.

Линия 9 просто ждет, когда что-то настанет, и предотвращает мерцание.

Он перемещается по одному пикселю за раз, основываясь на логической проверке, какая клавиша нажата, поэтому переход из стороны в сторону занимает чуть более 5 секунд.

Брайан
источник
2

Ruby with Shoes, 252 243 персонажа

Shoes.app{background white
i=image'i'
m=[0,0]
a=[:width,:height]
animate(99){i.left+=m[0]<=>i.left
i.top+=m[1]<=>i.top}
keypress{|k|d,v={?u=>[1,-1],?d=>[1,1],?l=>[0,-1],?r=>[0,1]}[k[0]];m[d]=[[m[d]+v*4,self.send(p=a[d])-i.send(p)].min,0].max}}

При этом используется окно с изменяемым размером, начинающееся с размера по умолчанию 600 x 500. Если вы измените размер окна, чтобы захватчик был пропущен, он вернется при нажатии следующей клавиши перемещения.

Хитрость для удовлетворения требований заключается в том, что позиция захватчика изменяется с шагом 4, но фактическое движение выполняется с шагом 1 при 99 кадрах в секунду.

manatwork
источник
2

Tcl / Tk , 242 байта

grid [canvas .c -w 400 -he 403 -bg #FFF -highlightt 0]
.c cr i 30 24 -i [image c photo -fi .png] -t p
lmap {k b x y} "Up 1]>25 0 -5 Right 0]<368 5 0 Down 1]<376 0 5 Left 0]>30 -5 0" {bind . <$k> "if \[lindex \[.c coo p] $b {.c move p $x $y}"}
sergiol
источник
Чтобы запустить его в любом Linux: у вас должны быть установлены Tcl и Tk; затем скопируйте код в файл, скажем так invaders.tcl; Вам также необходимо сохранить изображение как .pngв той же папке. Для запуска скрипта наберите wish invaders.tcl в оболочке. PS: он может быть более удачным, если код вместо этого вставляется в интерактивную оболочку, так как он поддерживает сокращенные команды по умолчанию.
sergiol
1

JavaScript (с использованием paper.js), 215 байт

v=new Raster("http://i.stack.imgur.com/CUweU.png",99,99);p=new Size(4,0)
onFrame=e=>{if(!v.isInside(view.bounds)){p=-p};v.position+=p}
onKeyDown=e=>{p=new Size([[0,-4],[0,4],[-4,0],[4,0]]["udlr".indexOf(e.key[0])])}

paper.js - это графическая среда JS, что означает, что она имеет много полезных функций, касающихся манипулирования изображениями. Для запуска просто скопируйте вышеупомянутое в раздел слева здесь , затем, чтобы переместить инопланетянина, щелкните один раз в правом разделе, чтобы выделить его. Если ваш браузер может с этим справиться, он должен работать со скоростью 60 кадров в секунду.

ivzem
источник