Autor
|
Tema: Hacer lo mismo de esta "cosa" de la película ochentera (Leído 3,389 veces)
|
Meta
|
Hola: Quiero hacer los dibujos exactamente lo mismo como en este ordenador ochentero de esta película exactamente indicado en el minuto 6:56 de este vídeo. Lo que he hecho hasta ahora son solo textos, en el cual no se el motivo, no me sale el rellenado de la parte derecha de la pantalla con el │ ASCII 179.  using System; using System.Threading; namespace The_Thing_La_Cosa_Consola_01_cs { class Program { static void Main(string[] args) { Console.Title = "The Thing - La Cosa - C#"; Console.WindowWidth = 38; // X ancho. Console.WindowHeight = 15; // Y altura. int tiempo = 1; // Cursor invisible. Console.CursorVisible = false; // Dibujar cuadro. DrawMarco(1, 1, 35, 14); // Escribir textos. Console.SetCursorPosition(2, 4); Escribir("PROJECTION: \n", 25); Console.SetCursorPosition(2, 5); Escribir("IF INTRUDER ORGANISM REACHES \n", 25); Console.SetCursorPosition(2, 6); Escribir("CIVILIZED AREAS . . . \n", 25); Thread.Sleep(100); Console.SetCursorPosition(2, 10); Escribir("ENTIRE WORLD POPULATION INFECTED \n", 25); Console.SetCursorPosition(2, 11); Escribir("27,000 HOURS FROM FIRST CONTACT. \n", 25); // En español. Thread.Sleep(2000); // Limpiar pantalla. Console.Clear(); // Dibujar cuadro. DrawMarco(1, 1, 35, 14); // Escribir textos. Console.SetCursorPosition(2, 3); Escribir("PROYECCIÓN: \n", 25); Console.SetCursorPosition(2, 4); Escribir("SI ORGANISMO INTRUSO ALCANZA \n", 25); Console.SetCursorPosition(2, 5); Escribir("ZONAS CIVILIZADAS . . . \n", 25); Thread.Sleep(100); Console.SetCursorPosition(2, 9); Escribir("TODA LA POBLACIÓN MUNDIAL INFECTÓ\n", 25); Console.SetCursorPosition(2, 10); Escribir("27,000 HORAS DESDE EL PRIMER\n", 25); Console.SetCursorPosition(2, 11); Escribir("CONTACTO. \n", 25); Console.ReadKey(); } public static void Escribir(string Cadena, int tiempo) { foreach (char letra in Cadena) { Console.Write(letra); Thread.Sleep(tiempo); } } private static void DrawMarco(int v1, int v2, int v3, int v4) { Console.ForegroundColor = ConsoleColor.Cyan; // Texto azul claro. Console.BackgroundColor = ConsoleColor.DarkBlue; // Fondo azul oscuro. Console.Clear(); // Para poner fondo azul oscuro en la pantalla completa. Console.CursorVisible = false; gotoXY(v1, v2, "┌"); for (int i = v1 + 1; i < v3; i++) { gotoXY(i, v2, "─"); } gotoXY(v3, v2, "┐"); for (int i = v2 + 1; i < v4; i++) { gotoXY(v3, i, "│"); } gotoXY(v3, v4, "┘"); for (int i = v3 - 1; i > v1; i--) { gotoXY(i, v4, "─"); } gotoXY(v1, v4, "└"); for (int i = v4 - 1; i > v2; i--) { gotoXY(v1, i, "│"); } //Console.CursorVisible = true; } private static void gotoXY(int v1, int v2, string cadena) { Console.SetCursorPosition(v1, v2); Console.WriteLine(cadena); Thread.Sleep(1); } } }
¿Alguna idea de como hacerlo? Por lo que parece, a pesar de que es del 1982, hoy en día exige mucho tiempo y complicado. Saludos.
|
|
« Última modificación: 4 Mayo 2019, 22:02 pm por Meta »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.921
|
Que quieras reproducir un efecto cinemático de software de los años 80, no significa que debas hacerlo como se podría hacer en los años 80... En lugar de una aplicación de consola puedes utilizar la tecnologia WindowsForms o WPF. Lo siguiente lo hice en WinForms en apenas 40 lineas de código:  Imports System.Drawing.Drawing2D Imports System.Threading Public Class Form1 Dim str As String = "PROJECTION: IF INTRUDER ORGANISM REACHES CIVILIZED AREAS... ENTIRE WORLD POPULATION INFECTED 27,000 HOURS FROM FIRST CONTACT." Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown ' Draw Panel Border. Using g As Graphics = Me.Panel1.CreateGraphics(), pen As New Pen(Color.FromArgb(255, 36, 244, 248), 6) pen.Alignment = PenAlignment.Inset g.DrawRectangle(pen, Me.Panel1.ClientRectangle) End Using ' Clear label text and set text font. Me.Label1.Text = "" Me.Label1.Font = New Font("MODESEVEN", 20) Me.Update() Thread.Sleep(1000) ' Write the text. For Each c As Char In Me.str Me.Label1.Text &= c Me.Label1.Update() Thread.Sleep(80) Next c End Sub End Class
El form consiste de un Panel y un Label, nada más. Aquí puedes descargar el proyecto: Y la fuente true-type que utilicé:
Logicamente si pretendes reproducirlo en una ventana de consola, es un procedimiento bastante más tedioso al carecer de funcionalidades avanzadas de dibujado. Para empezar, el rectángulo o borde lo puedes dibujar de manera muy sencilla con mi código reusable de ConsoleRectangle: Y para escribir el texto disculpa que te diga pero yo sinceramente alucino con la que te has montado en tu código. A estas alturas y todavía sigues haciendo estas cosas... // Escribir textos. Console.SetCursorPosition(2, 3); Escribir("PROYECCIÓN: \n", 25); Console.SetCursorPosition(2, 4); Escribir("SI ORGANISMO INTRUSO ALCANZA \n", 25); Console.SetCursorPosition(2, 5); Escribir("ZONAS CIVILIZADAS . . . \n", 25); Thread.Sleep(100); Console.SetCursorPosition(2, 9); Escribir("TODA LA POBLACIÓN MUNDIAL INFECTÓ\n", 25); Console.SetCursorPosition(2, 10); Escribir("27,000 HORAS DESDE EL PRIMER\n", 25); Console.SetCursorPosition(2, 11); Escribir("CONTACTO. \n", 25);
Mira, simplemente declara una variable multilinea con el texto a escribir (del mismo modo que en el código que he mostrado arriba) y con un foreach en C# iteras los caracteres, haces una pausa de 80-100 ms entre cada caracter y lo escribes. fin. Ah, y si quieres modificar la fuente de la instancia de la consola actual, deberás usar la función SetCurrentConsoleFontEx: Hice este código que podría servir como ejemplo...  Imports System.ComponentModel Imports System.Drawing Imports System.Runtime.InteropServices Imports System.Security Imports System.Text Imports System.Threading Module Module1 ReadOnly str As String = "PROJECTION: IF INTRUDER ORGANISM REACHES CIVILIZED AREAS... ENTIRE WORLD POPULATION INFECTED 27,000 HOURS FROM FIRST CONTACT." Sub Main() Console.Title = "The Thing - La Cosa" Console.WindowWidth = 60 Console.WindowHeight = 20 ' Paint background. Console.BackgroundColor = ConsoleColor.DarkBlue Console.Clear() ' Draw border. Console.ForegroundColor = ConsoleColor.Cyan Dim rc As ConsoleRectangle = New Rectangle(2, 2, Console.WindowWidth - 4, Console.WindowHeight - 4) rc.Write() ' Draw Text. Dim x As Integer = (rc.Width \ 5) Dim y As Integer = (rc.Height \ 3) ConsoleUtil.SetConsolefont("Consolas", bold:=False) Console.SetCursorPosition(x, y) For Each c As Char In str If c.Equals(ControlChars.Cr) Then Console.SetCursorPosition(x, Interlocked.Increment(y)) Continue For End If If c.Equals(ControlChars.Lf) Then Continue For End If Console.Write(c) Thread.Sleep(80) Next Console.ReadKey(intercept:=True) End Sub End Module
El proyecto (con el resto del código que no he mostrado) lo puedes descargar aquí: Nótese que el proyecto que he compartido incluye extractos del código fuente de mi librería comercial DevCase for .NET Framework para programadores de C# y VB.NET. También incluí un método para cambiar la fuente de texto de la consola, el cual lo he escrito practicamente para responderte a tu duda, y no lo he testeado mucho, pero encontré problemas para cambiarle el tamaño a la fuente por que al cambiarle el tamaño también se agranda la ventana de la consola. Parece ser el comportamiento por defecto de Windows, así que dejé el tamaño por defecto para no comerme mucho la cabeza. Tampoco me esmeré nada para alinear el texto dentro del rectángulo ya que es solo un ejemplo y no quiero darle más vueltas haciendo cálculos más sofisticados, eso te lo dejo a ti. Saludos.
|
|
« Última modificación: 5 Mayo 2019, 14:54 pm por Eleкtro »
|
En línea
|
|
|
|
|
Meta
|
Fantático ejemplos visuales.  Si te fija en el vídeo, primero la formación del rectángulo se hace poco a poco, no de golpe, algo parecido hice en modo consola. En Windows Form el cuadro se hace directo, no poco a poco con GDI+, por eso mejor usar los ASCII para la formación del retángulo como en modo consola. Por ahora solo he heche textos en Windows Form. Añado un timer, luego hago el resto. Con Window Form. using System; using System.Windows.Forms; namespace The_Thing_La_Cosa { public partial class Form1 : Form { public Form1() { InitializeComponent(); } string texto = @" PROJECTION: IF INTRUDER ORGANISM REACHES CIVILIZED AREAS . . . ENTIRE WORLD POPULATION INFECTED 27,000 HOURS FROM FIRST CONTACT. "; int contador = 0; private void timer1_Tick(object sender, EventArgs e) { label1.Text += texto[contador++]; if (contador >= texto.Length) { timer1.Enabled = false; Console.Beep(600, 25); // Console.Beep(frecuencia, duracion); } } private void Form1_Load(object sender, EventArgs e) { timer1.Enabled = true; } } }
Lo intenté hacer con WPF pero no tiene el componente timer, habrá que crear hasta su propio evento y vete a saber cuántos códigos más. Gracias por compartir.
|
|
« Última modificación: 5 Mayo 2019, 17:24 pm por Meta »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.921
|
En Windows Form el cuadro se hace directo, no poco a poco con GDI+
Lo puedes hacer como quieras, de forma directa, o dibujando una linea poco a poco (usando un For)... Saludos.
|
|
|
En línea
|
|
|
|
Meta
|
Vale.  Código no hecho por mi. private void Form1_Load(object sender, EventArgs e) { Thread tr = new Thread (new ThreadStart (drawlines )); tr.Start(); } public delegate void Function(); Point A = new Point (5, 5); Point B = new Point (5, 5); private void drawlines() { Thread.Sleep(1000); drawMarco(); Thread.Sleep(25); SetText("2", "PROJECTION:"); SetText("3", "IF INTRUDER ORGANISM REACHES"); SetText("4", "CIVILIZED AREAS . . ."); Thread.Sleep(100); SetText("7", "ENTIRE WORLD POPULATION INFECTED"); SetText("8", "27,000 HOURS FROM FIRST CONTACT."); Thread.Sleep(2000); clrscr(); drawMarco(); SetText("1", "PROYECCIÓN:"); SetText("2", "SI ORGANISMO INTRUSO ALCANZA"); SetText("3", "ZONAS CIVILIZADAS . . . "); Thread.Sleep(100); SetText("7", "TODA LA POBLACIÓN MUNDIAL INFECTÓ"); SetText("8", "27,000 HORAS DESDE EL PRIMER"); SetText("9", "CONTACTO."); Thread.Sleep(2000); Application.Exit(); } private void clrscr() { A = B; Graphics ps = this.CreateGraphics(); ps .FillRectangle(new SolidBrush (Color .DarkBlue), 0, 0, this.Width, this.Height); foreach (Control control in Controls) { this.Invoke(new Function (delegate () { control.Text = ""; })); } } private void SetText(string name, string txt) { string nombre = $"label{name}"; foreach (char letra in txt) { this.Invoke(new Function (delegate () { Controls[nombre].Text += letra; })); Console.Beep(600, 25); Thread.Sleep(25); } } private void drawMarco() { for (int i = 5; i < this.Width - 20; i++) SetMarco(i, B.Y); for (int i = 5; i < this.Height - 40; i++) SetMarco(B.X, i); for (int i = this.Width - 20; i > 5; i--) SetMarco(i, B.Y); for (int i = this.Height - 40; i > 5; i--) SetMarco(B.X, i); } private void SetMarco(int x,int y) { this.Invoke(new Function (delegate () { A = B; Graphics ps = this.CreateGraphics(); ps .DrawLine(new Pen (Color .Blue, 3), A, B ); })); Thread.Sleep(1); }
|
|
|
En línea
|
|
|
|
|
|