Zalogowany jako: gość

Forum

Wątek: Nowe API dla programów

Wróć do listy wątków

2 z 3

Poprzednia
Następna

21 z 59: daszekmdn

Czy będzie możliwość odtworzenia dowolnego dźwięku?
W grę wchodzi tylko format ogg jak w bgt?

12.12.2019 13:41

22 z 59: pajper

Dowolnego, jaki tylko obsługuje Elten, czyli... wav, mp3, ogg, aac, flac, opus, aiff, wma, m4a, pewnie o czymś zapomniałem.
Ale ogg jest preferowane, bo po prostu jego implementacja jest najlepiej napisana, tzn. załadowanie ogg do pamięci jest nawet 8-9 razy szybsze od mp3. To niby mała różnica, bo w grę wchodzą milisekundy, ale... ziarnko do ziarnka...
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
12.12.2019 13:44

23 z 59: pajper

Oczywiście ograniczeniem i zaletą jest to, że gry będą uruchamiane w środowisku Eltena, na razie tylko jako programy, potem rozważę opcję jakiejś pseudokompilacji, ale i tak będą wymagały zainstalowanego Eltena.
Wada to z przyczyn oczywistych, zaleta, bo umożliwi banalnie proste konkurowanie graczy, robienie tablic wyników itp.
Pracuję także nad API do tego, które pozwoli prostymi funkcjami na tworzenie tablic osiągnięć itd, a także na komunikację między użytkownikami przez serwer Eltena, bez public IP, to do multiplayerek, ale raczej nie w najbliższej becie.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
12.12.2019 13:48

24 z 59: pajper

Wracam do map na moment.
No i do czegoś przyda się Revina.
Przekopiowałem jej API do prostego tworzenia obiektów. Obiekty mogą się poruszać, wydawać dźwięk, który się przesuwa zależnie od odległości.
Tutaj przykład:
map = Map.new(10,10) {
object(5,5) { # obiekt na współrzędnych 5,5
sound(appfile("wolf.ogg")) # dźwięk wydawany przez obiekt
sound_range(5) # zasięg, z którego obiekt jest słyszany
move_type(:random) # jak się porusza: :fixed, :random, :follow
range(0) # zasięg, z którego można wejść w interakcje, 0 oznacza stanie na tym samym polu
on(:range) {
play(appfile("roar.ogg")) # gdy znajdziemy się w zasięgu zdarzenia
}
on(:touch) { # gdy dotkniemy obiektu
}
on(:key_enter) {
# gdy wciśniemy na nim enter
}
}
}
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
12.12.2019 13:55

25 z 59: daszekmdn

To ja przepiszę Mao adventure ;) a przynajmniej podejme próbę.

12.12.2019 13:59

26 z 59: nuno69

Dawid, ale właśnie mi timery byłyby do czegoś takiego potrzebne., Proszę, rzuć mi referencją na nuno69a at gmail dot com jak już będzie...
- "Intelligence and wisdom is like jam. The less you have, the harder you're trying to spread it arround." - French proverb
12.12.2019 15:39

27 z 59: pajper

Dwa rodzaje timerów, globalne i mapy.
Globalne dotyczą wszystkiego:

timer = Timer.new(1, true) {
# ten kod będzie wykonywał się co jedną sekundę
# aż ktoś nie wywoła timer.stop
}

Drugi rodzaj to timery mapy. Powstały, by nie musieć ręcznie zamykać wszystkich timerów (mapa sama je zamyka przy wywołaniu dispose), ale także by móc bez przeszkód otwierać różnego rodzaju menu, zdarzenia itp. ze wstrzymaniem timerów:

timer = @map.timer(0.5, true) {
# ten kod będzie wywoływał się co pół sekundy, ale tylko, gdy mapa jest wyświetlana
# można zrobić timer.stop albo wyczyścić wszystkie timery komendą @map.clear_timers
}
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
13.12.2019 08:45

28 z 59: nuno69

Czyli teraz mogę zrobić własny algorytm poruszania, ciekawe czy zaimplementuję "STAR Node"
- "Intelligence and wisdom is like jam. The less you have, the harder you're trying to spread it arround." - French proverb
13.12.2019 12:06

29 z 59: pajper

Napisałem prosty sample, będzie w Eltenie 2.4 Beta 6.
Gra to nudna, banalna i o prostej mechanice strzelanka, ale jest przykład.
Mamy pistolet i musimy strzelać do spawnujących się potworów.
Controlem strzelamy, shiftem przeładowujemy. W trakcie gry pojawiają się na mapie dodatkowe magazynki z amunicją i punkty leczenia.
To zasadniczo tyle.
Całość zajęła dokładnie 96 linijek.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
14.12.2019 01:04

30 z 59: daszekmdn

Przepisz tam grę kocie ;)

14.12.2019 01:05

31 z 59: pajper

Zakończyłem prace nad nowym API, no, prawie.
Poniżej wklejam kod przykładowej, małej gierki (98 linijek). To ostatni moment na zgłaszanie wszystkich sugestii, niepewności co do nazw funkcji, składni itp.

Gra to typowy, prosty shooter trwający na mapie o wymiarach 20x20 pól. Co losowy czas między 3 a 8 sekund na mapie pojawia się potwór (w odległości min. 5 pól od gracza) i zaczyna podążać w jego stronę.
W losowym czasie między 20 a 40 sekund pojawia się pole lecznicze w losowym miejscu. Po wejściu na nie, te znika, a gracz odzyskuje wszystkie punkty życia i amunicję.
Klawiszem shift się przeładowuje, a controlem strzela. Dodatkowo A podaje pozostałą amunicję, H punkty życia, a C ilość zabitych przeciwników.
Grę dołączę jako sample do następnej bety.
Kod udostępniam celowo bez komentarzy, by sprawdzić jego czytelność, jednak w wypadku niepewności co do którejś linijki proszę o zapytanie. :)






class Program_Shooter < Program
Name="Shooter"
Author="pajper"
Version="1.0"
def main
menu=Menu.new {
option("New game") {
return game
}
option("Game info") {
alert("Your goal is to shoot as many enemies as you can before they will defeat you. Simple. Shoot using control key, reload using shift key.")
return main
}
option("Exit") {}
}
menu.open
finish
end
def game
@hp=10
@ammo=10
@loaded=false
@killed=0
@map = Map.new(20,20) {|m|
m.direction_delay
m.direction_sound(appfile("direct.ogg"))
m.move_sound(appfile("step.ogg"))
m.timer(3..8, true) {
x,y=m.random_position(5)
m.object(x,y){|o|
o.sound(appfile("monster.ogg"))
o.move_type(:follow)
o.on(:touch, 1) {
o.play(appfile("attack.ogg"))
@hp-=1
if @hp<=0
m.dispose
delay(0.5)
alert("You were killed. You have shot #{@killed} monsters.")
end
}
}
}
m.on(:key_escape) {@map.dispose}
m.on(:key_shift) {
if @loading!=true
if @ammo>0 and @loaded==false
@loading=true
@ammo-=1
m.timer(0.5) {
@loaded=true
@loading=false
}.start
play(appfile("reload.ogg"))
end
end
}
m.timer(20..40, true) {
x,y=m.random_position
m.object(x,y){|o|
o.sound(appfile("healing.ogg"))
o.sound_range(10)
o.on(:touch) {
@hp=10
@ammo=10
play(appfile("heal.ogg"))
m.delete_object(o)
}
}
}
m.on(:key_h) {
speak(@hp.to_s)
}
m.on(:key_a) {
speak(@ammo.to_s)
}
m.on(:key_c) {
speak(@killed.to_s)
}
m.on(:key_control) {
if @loaded==true
play(appfile("shoot.ogg"))
for o in m.objects
if m.distance(o.x,o.y)<5 and m.directs?(o.x,o.y)
o.play(appfile("fall.ogg"))
@killed+=1
m.delete_object(o)
break
end
end
@loaded=false
end
}
}
@map.show(10,10)
return main
end
end
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 11:29

32 z 59: pajper

Aaaa, miałem jeszcze wyjaśnić kilka możliwych niepewności co do składni Rubiego.
Są tam takie linijki, jak:

@map = Map.new(20,20) {|m|
albo
m.object(x,y){|o|

To taka typowo Rubiowska składnia. Kiedy definiujemy mapę czy obiekt, to słowo w kreseczkach jest nazwą zmiennej, która go będzie zawierała. Gdybyśmy zrezygnowali z tych kresek, moglibyśmy zrobić tak:
@map=Map.new(20,20) {
move_sound(appfile("move.ogg"))
sound_delay
}

itd. Tylko wtedy stracilibyśmy możliwość odwoływania się do zmiennych naszego programu. Ta nazwa zmiennej w kreseczkach sprawia, że wywołujemy nasze polecenia w kontekście programu, a do mapy, obiektu itp. odwołujemy się przez jego referencję.
Gdyby z nich zrezygnować w tym przykładzie, moglibyśmy stworzyć mapę, przeciwników, ale nie byłoby sposobu, by zapamiętywać ilość amunicji, hp czy też informacji o załadowaniu broni, bo... stracilibyśmy możliwość odniesienia do zmiennych naszego programu.
Mam nadzieję, że dość jasno wyjaśniłem.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 11:39

33 z 59: denis333

Hmm. Ja ze strony użytkownika rozszerzył bym losowość respienia się różnych rzeczy na mapie na przykład do jednej minuty. co by było jeszcze ciekawiej.

16.12.2019 11:54

34 z 59: tomecki

Pamiętaj Denisie, że to nie jest faktyczna gra tylko takie demo, które ma pokazać jak się programuje więc w gruncie rzeczy wszelkie wartości czasów, rozmiarów i innych takich mogą być dowolne.
Szczerze mówiąc osobiście chciałbym aby możliwe było łatwe implementowanie jakiegoś modelowania dźwięku tj. albo Openall, bo tam jest w cholerę efektów więc jakieś pogłosy czy inne takie możnaby tworzyć względnie prosto, a tego w grach audio rozpaczliwie brakuje, do tego jakiś prosty generator audio przydatny przy różnego rodzaju celownikach czy innych wskaźnikach, bo tego też nie ma, ale obawiam się, że tego raczej nie będzie.

16.12.2019 14:23

35 z 59: tomecki

Przy okazji, czy będzie jakaś łatwa możliwość skorzystania z aplikacji zewnętrznych np. konsolowych? Pytam, bo ciągle chodzi mi po głowie ten nieszczęsny konwerterek audio, a w dłuższej perspektywie i edytor, ale jestem na prawdę cienki jeśli chodzi o tworzenie własnych algorytmów więc im łatwiej skorzystać z czegoś, co już jest tym dla mnie lepiej.

16.12.2019 14:26

36 z 59: pajper

EltenAPI nie zajmuje się efektami dźwiękowymi. To znaczy jest zaimplementowanych kilka algorytmów, jest prosta funkcja do odtwarzania dźwięków, plus mapki implementują stereo i zmianę wysokości/głośności. Z zasady jednak implementacja własnego interfejsu dla dźwięku w EltenAPI mija się z celem i tylko komplikowałaby sprawę.
Elten wykorzystuje bibliotekę Bass i jej implementacja dla Rubiego jest jak najbardziej do użycia w dowolnym programie, zrobię sample. Ona pozwala na podstawowe rzeczy: stereo panning, wysokość, głośność. Jest też sporo efektów FX.
Przyznam, że się nimi nie interesowałem, ale zerknę na nie i umieszczę w Samplu. Ale to Bass, nie Elten API.
Są także implementacje OpenAL czy FMOD dla Rubiego i nic nie stoi na przeszkodzie, by ich twórca aplikacji dla Eltena użył, wystarczy dodać do programu odpowiednie pliki i skrypty.

Co do aplikacji konsolowych, mamy Rubiowski interfejs system i potoki w Elten API, można ich najbardziej użyć. Tak Elten komunikuje się np. z Youtube-DL.
Klasa ChildProc, też będzie sample.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 14:31

37 z 59: zywek

Hm, prosty algorytm tych strzałów tam jest. Nawet nie sprawdza, czy aby na pewno ten pseudopocisk poleciał tam, gdzie miał dokłądnie, albo ja jestem ślepy.

16.12.2019 14:32

38 z 59: pajper

@żywek
Algorytm jest banalny, ale to tylko sample. Ale sprawdza. Funkcja Map#directs? sprawdza, czy gracz skierowany jest w odpowiednią stronę.
Interesują Ciebie te linijki:

m.direction_delay # sprawia, że pierwszy krok w nową stronę odwraca gracza, to znaczy imituje obroty
m.direction_sound(appfile("direct.ogg")) # tu jest dźwięk na obracanie się gracza
i w implementacji strzału
if m.distance(o.x,o.y)<5 and m.directs?(o.x,o.y)
sprawdza, czy odległość do obiektu o jest mniejsza niż 5 i czy gracz jest w jego stronę skierowany.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 14:35

39 z 59: zywek

No własnie, ale to nie jest miarodajne wg mnie jakoś tak bardzo. Pewnie tm można zrobić więcej i wiem, że to tylko demo, ale jednak.

16.12.2019 14:35

40 z 59: pajper

Jak przeciwnik jest przed graczem mniej-więcej, a gracz patrzy do przodu, strzał trafi. Jak gracz idzie w lewo czy w tył, nie trafi.
Oczywiście, strzelanie tu jest banalne i wymaga obrotu mniej-więcej w stronę wroga, bez precyzyjnego kierowania, ale to na potrzeby sample wystarczy.
Precyzyjniejszy system byłby do implementacji własnej.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 14:37

Wróć do listy wątków

2 z 3

Poprzednia
Następna

Nawigacja


Copyright (©) 2014-2024, Dawid Pieper