Skocz do zawartości

Wyśrodkowanie textu


Rekomendowane odpowiedzi

witam
chce zrobic pojawiajaca sie wiadomosc z wysrodkowanym textem
tzn.nie ważne jaki text bedzie dlugi chce by wiadomosc ktora sie wyswietli
na kazdej linijce miala max 40 znakow(jak bedzie wiecej to ma przeskoczyc na nastepna linijke, i byla wysrodkowana na kazdej lini

zmienna z tekstem to global.wiadomosc

ekran ma szerokosc 1280/800
wyswietlanie textu na srodku ekranu to:
draw_text(640,400,global.wiadomosc)

co mam dalej zrobic ?

Odnośnik do komentarza
Udostępnij na innych stronach

Poczytaj o:

string_width(string)

https://docs.yoyogames.com/source/dadiospice/002_reference/strings/string_width.html

string_height(string)

https://docs.yoyogames.com/source/dadiospice/002_reference/strings/string_width_ext.html

string_width_ext(string, sep, w)

https://docs.yoyogames.com/source/dadiospice/002_reference/strings/string_width_ext.html

string_height_ext(string, sep, w)

https://docs.yoyogames.com/source/dadiospice/002_reference/strings/string_height_ext.html

 

To może Ci się na przyszłość przydać. Dzięki temu możesz sam wyliczyć dokładną pozycję tekstu. Co do Twojego problemu z linijką niżej. Od tego jest "#", czyli nowa linia.  Np.: "Tekst#Tekst2" zostanie wyświetlony jeden pod drugim:

Cytuj

Tekst
Tekst2

Musisz stawiać "#" w stringu co 40 znaków. Nie wiem jak dokładnie to u Ciebie działa, ale możesz to robić, albo ręcznie jeśli jest taka opcja w Twoim przypadku, albo musisz pod to napisać funkcję. To rozwiązanie jest o tyle fajne, że druga i każda kolejna linijka jest wyśrodkowywana według draw_set_halign.

Jeśli # odpada to poczytaj o tych funkcjach które podałem wyżej. Wyśrodkowanie tekstu który ma draw_set_halign(fa_left) - czyli domyślną wartość - robisz po prostu tak:

draw_string(x - string_width(str)/2, y, str);

Przy czym str to Twój string oczywiście ;)

Obliczenie nowej linii to po prostu:

draw_string(x - string_width(str)/2, y, str); //linia 1
draw_string(x - string_width(str2)/2, y + string_height(str), str2); //linia 2

Przy czym str to string linii pierwszej, a str2 to string linii drugiej.

Czyli dodajesz do Y wysokość stringa pierwszego.

Możesz też użyć według poprzedniej metody:

draw_set_halign(fa_center);
draw_string(x, y, str); //linia 1
draw_string(x, y + string_height(str), str2); //linia 2

Obie opcje dadzą ten sam efekt co:

draw_set_halign(fa_center);
draw_string(x, y, str + "#" + str2)

W zasadzie opcja z płotkiem tak, czy siak wydaję się chyba najprostsza. "fa_center" załatwi sprawę za Ciebie, a # możesz dodać na etapie algorytmu budowania takiego stringa. Czyli co 40 znaków dodawaj # i tyle.

Odnośnik do komentarza
Udostępnij na innych stronach

12 godzin temu, gnysek napisał:

draw_text_ext i draw_set_halign załatwią sprawę, używam od lat.

Tyle, ze parametr "W" w draw_text_ext liczy po pikselach, a nie znakach. Najczęściej to załatwia sprawę, ale może Ice Cube chce typowo 40 znaków wtedy draw_text z płotkiem i draw_set_halign powinien dać radę lepiej. Pytanie czy na prawdę mu to potrzebne, bo wiadomo, że draw_text_ext jest szybsze i prostsze. A te funkcje przytoczyłem, bo bardzo fajnie mieć ich świadomość. Ja używam ich czasami jeśli nie muszę co prawda wyśrodkowywać tekstu, ale potrzebuję wyliczyć jakaś mniej typową pozycję wyświetlania.

Odnośnik do komentarza
Udostępnij na innych stronach

draw_text_ext - jest fajne,ale liczy w pixelach ,a jak to policzyc w "stringach",chciałbym wiedzieć tak na przyszłość jak sie robi działania na tych "stringach" :D

 

znalazłem taką funkcje string_length(str) 

 

if string_length(global.wiadomosc)>40  znajdz miejsce miedzy slowami(spacje) w okolicach 40 i dodaj w tym miejscu #

 

show_message(tekst)

 

ktoś potrafiłby to ogarnąć?

 

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Ale 40 liter "i" a 40 liter "w" to jest 5x tyle szerokości, dlatego w pikselach lepiej moim zdaniem.

 

Jednak, zeby nie powiedzieć, że się nie da, to:

 

https://www.gmlscripts.com/script/string_wordwrap

 

string_wordwrap(string,40,"\n\r", false); // dla gms 1 można '#'
Odnośnik do komentarza
Udostępnij na innych stronach

Panowie, mój problem jest nieco inny, ale też dotyczy tekstu , nie chciałem więc zakładać nowego tematu. Chodzi mi o zawijanie tekstu.

 

Funkcja draw_text_ext pozwala na zawinięcie tekstu, jeśli przekroczy on odpowiednią ilość pixeli. Problem polega na tym, że dotyczy to tylko słów odseparowanych spacją. Jeśli string zawarty w tejże funkcji będzie składał się z jednego, długaśnego słowa, którego długość przekracza długość jednej całej linijki, to wrapowanie zostanie zignorowane :( . Czy wie ktoś jak sprawić, aby funkcja draw_text_ext wrapowała też pojedyńcze słowa, które są dłuższe niż długość jednej linijki?

 

Będę wdzięczny za pomoc,

nowy_user!

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Ma łamać nawet w pół słowa?

 

var stack = '', result = '', text = 'Lorem ipsum dolor sit amet', len = 40; // 40px;

for(i=1; i<=string_length(text); i++) {

  var c = string_char_at(text, i);

  if (string_width(stack + c) > len {

    result += stack + '#';

    stack = '';

  } else {

    stack += c;

  }

}

 

result += stack;

return stack;

 

Jakoś tak, ale to się na pewno wywali, jak len będzie mniejsze niż najszersza litera.

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki Gnysek, ale nie do końca mi o to chodziło...

 

W Twoim przykładzie odnosimy się do ilości liter w danej zmiennej string, a mi chodzi po prostu o prawie taką samą funkcję jak draw_text_ext, gdzie możemy sobie wpisać długość linii ( wyrażoną w pikselach ) i po przekroczeniu tej wartości tekst jest przeniesiony do następnej linijki. To wszystko fajnie działa z funkcją draw_text_ext, do momentu, gdy jeden wyraz jest dłuższy (  w pikselach) od tej wartości podanej w draw_text_ext, wtedy dochodzi do takiej sytuacji, którą przedstawiam poniżej w obrazku:

 

image.png.354305a28492d43970861bbce51849f8.png

 

Chciałbym móc narysować tekst dokładnie tak jak to robię funkcją draw_tex_ext z tą jedną różnicą, że gdy dane słowo jest dłuższe ( w pikselach, a nie w ilości liter) niż wartość, którą podaje , to aby dzieliło ten wyraz i jego drugą część, która nie zmieściła się w jednej linijce, przeniosło do kolejnej linijki.

 

Mam nadzieję, że teraz opisałem mój problem bardziej klarownie, będę wdzięczny za pomoc :)

 

pozdrawiam,

nowy_user

 

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

Cześć, możesz podzielić słowa które są dłuższe niż dana szerokość i rysować tekst za pomocą draw_text_ext. Skrypt do łamania słów:

/// scr_wrap_words(string,w)
var text = argument0, len = argument1;

var strlen = string_length(text);
var i = 1, c = '', word = '', result = '';

while (i < strlen + 1) {
    c = string_char_at(text, i++);
    
    if (string_width(word + c) > len) {
        word += '#';
    }
    
    word += c;
    
    if (c == ' ') {
        result += word;
        word = '';
    }
}

return result + word;

 

W połączeniu z draw_draw_text:

var text = scr_wrap_words("Lorem ipsum dolor sit amet, andverylongwordthatmustbesplitted.", 100);

draw_set_color(c_black);
draw_rectangle(10, 10, 110, 210, false);

draw_set_color(c_white);
draw_text_ext(10, 10, text, 15, 100);

 

Rezultat powinien być wystarczający:

gI2NzjV.png

Odnośnik do komentarza
Udostępnij na innych stronach

52 minuty temu, Konrad-GM napisał:

draw_text_ext(10, 10, text, 15, 100);

 

 

 

@Konrad-GM , dziękuję za ten kod, rzeczywiście działa,  no prawie bez zarzutu.  W sytuacji gdy przed tym dłuższym słowem dodamy więcej niż jedną spację tekst dalej będzie wychodzić poza kwadrat :( Po wpisaniu takiego kodu:

 

var text = scr_wrap_words("Lorem ipsum dolor sit amet,        andverylongwordthatmustbesplitted.", 100);

draw_set_color(c_black);
draw_rectangle(10, 10, 110, 210, false);

draw_set_color(c_white);
draw_text_ext(10, 10, text, 15, 100);

Mamy następującą sytuację: 

 

image.png.b824fe91900f356dc65536dc5afd9d58.png

 

Co ciekawe, jeśli zamieniłbym spację na jakikolwiek inny znak np. _  to działałoby bez zarzutu... tylko te przeklęte spacje psują cały efekt :(Gdybyś miał jakiś pomysł jak to naprawić to będę wdzięczny, choć już i tak dużo zrobiłeś wysyłając poprzedni kod.

 

Dzięki i pozdrawiam!

nowy_user

 

 

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

A mój skrypt nie działał dobrze ? Nie ten z gml scripts, ten drugi (włącz sortowanie w temacie po dacie, a nie po ocenie).

W skrypcie Kondrada-GM problemem jest fragment:

if (c == ' ') {
        result += word;
        word = '';
    }

który jak widzi spację, uznaje, że słowo się zmieściło i dodaje na result, przestając zliczać - tymczasem result powinno się resetować wraz z dodaniem znaku # (a najlepiej jeśli znak C to spacja albo pierwszy znak w linii go nie dodawać).

 

Czyli jakoś tak:

 

var stack = '', result = '', text = 'Lorem ipsum dolor sit amet', len = 40; // 40px;
for(i=1; i<=string_length(text); i++) 
  var c = string_char_at(text, i);
  if (string_width(stack + c) > len {
    result += stack + '#';
    stack = (c == ' ') ? '' : c; // W GMS1: if (c == ' ') stack = '' else stack = 'c';
  } else {
    stack += c;
  }
}

result += stack;
return stack;

 

Odnośnik do komentarza
Udostępnij na innych stronach

  1. Gnysek, użyłem kodu według Twoich zaleceń, stworzyłem skrypt scr_wrap_words o następującej zawartości (dla GMS 1.4999):
/// scr_wrap_words(string,w)

var text = argument0, len = argument1;
var stack = '', result = '';

for(i=1; i<=string_length(text); i++) 
{
  var c = string_char_at(text, i);
  if (string_width(stack + c)) > len 
  {
    result += stack + '#';
    if (c == ' ') stack = '' else stack = 'c';
  } 
  else 
  {
    stack += c;
  }
}

result += stack;
return stack;

 

 a następnie wywołałem go z mojego obiektu za pomocą skryptu:

var text = scr_wrap_words('aaaaaaaaaaaaaaaaaaaaaaaaaaa',100);

draw_set_color(c_black);
draw_rectangle(10, 10, 110, 210, false);

draw_set_color(c_white);
draw_text_ext(10, 10, text, 15, 100);

Czyli jak widać , nawet nie kombinowałem ze spacją, a efekt jest taki:

image.png

 

... czyli ucięło kilkanaście pierwszych 'a' , tych które normalnie mieściłyby się w prostokącie, zostawiło tylko te, które miały wychodzić poza prostokąt, a dodatkowo, przed całym tekstem dodało literkę 'c', której w ogóle nie wprowadzałem. W takiej sytuacji nie dodawałem nawet podwójnej spacji, żeby się jeszcze bardziej nie wykrzaczyło. Hm.. co tu mogło pójść nie tak?

 

EDIT 

chyba wiem co, w Twoim skrypcie na końcu powinno być return result; zamiast return stack;  tak mi się wydaję, że po małej korekcie teraz już chyba działa ok :-) Wielkie dzięki za pomoc!

 

EDIT 2 , a jednak jeszcze nie działa tak jak należy, dla kodu : 

 

var text = scr_wrap_words('Tymon  Piotr   Usprawiedliwienie',100);


draw_set_color(c_black);
draw_rectangle(10, 10, 110, 210, false);

draw_set_color(c_white);
draw_text_ext(10, 10, text, 15, 100);

 

wyświetla się takie coś:

 

image.png.35d5ac3c15ce5744875560bcbc9936cc.png

 

czyli tekst właściwie się zawija, nawet przy trzech spacjach przed danym słowem, ale są dwa problemy:

1)  Zawija słowo Piotr, które spokojnie mogłoby się zmieścić cały w drugiej linijce. Kod powinien 'łamać' tylke te bardzo długie słowa, których długość (wyrażona w pikselach) wynosi więcej niż argument1. Czyli słowo Piotr powinno być tu przeniesione w całości do drugiej linijki, natomiast słowo Usprawiedliwienie jest właściwie podzielone

2) Skrypt dodaje  niepotrzebnie literkę c na początku kolejnych linijek, bez żadnego powodu. Własciwie to nie dodaje tylko podmienia, i zamiast Piotr mamy Piocr. 

 

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

Ok, przerobiłem swój kod żeby łamał słowa jak i linie, traktując ciąg spacji również jak słowo:

/// scr_wrap_string(string,w)
var text = argument0, len = argument1;

var strlen = string_length(text);
var i = 1, c = '', w = '', word = '', line = '', result = '';

while (i <= strlen) {
    c = string_char_at(text, i++);
    w = string_char_at(word, 1);

    // lamanie tekstu
    if (c == '#') {
        result += line + word + '#';
        line = '';
        word = '';
        w = '';
        continue;
    }

    // przelamujemy linie
    if (line != '' && string_width(line + word) > len) {
        result += line + '#';
        line = '';
    }

    // przelamujemy slowo
    if (string_width(word + c) > len) {
        line += word + '#';
        word = '';
        w = '';
    }

    // budujemy slowo
    // ciag spacji traktujemy jako slowo
    if ((c == ' ' && (w == '' || w == ' ')) || (c != ' ' && w != ' ')) {
        word += c;
    }
    else {
        line += word;
        word = c;
        
        // linii nie zaczynamy spacja
        if (string_char_at(line, 1) == ' ') {
            line = '';
        }
    }
}

result += line;
result += word;
return result;

 

Jako, że teraz skrypt ten łamie tekst również w linii, nie potrzebujemy używać draw_text_ext a wystarczy draw_text:

var text = scr_wrap_string("Lorem ipsum dolor sit amet,                     andverylongwordthatmustbesplitted", 100);

draw_set_color(c_black);
draw_rectangle(10, 10, 110, 210, false);

draw_set_color(c_white);
draw_text(10, 10, text);

 

OYiWEyh.png

Odnośnik do komentarza
Udostępnij na innych stronach

Zgadza się Gnysek, bardzo dobrze Ci poszło,  ja np. nie potrafię sobie wyobrazić kodzenia bardziej skomplikowanych skryptów tylko głowie, zwłaszcza od czasu, gdy korzystam z gmlive to większość robię metodą prób i błędów. 

 

Dzięki jeszcze raz za pomoc. Teoretycznie zastanawiam się, czy można jeszcze jakoś sprawić, aby tekst który wychodzi poza kwadrat od dołu ( czyli gdy napiszemy wystarczająco dużo tekstu) nie był w ogóle wyświetlany…. ale nie chciałbym nadwyrężać Waszej życzliwości i gościnności.

 

Jeszcze raz dziękuję i pozdrawiam :-)

nowy_user

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Ale możesz przecież rysować na jednym surface, nie musisz mieć 50. Rysuj, czyść, rysuj, czyść. To powinno być w miarę stabilne.

 

 

ale glScissor to by naprawdę ratował sporo, nawet gry rpg na starych konsolach wykorzystywały to do obcinania tekstów.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...